###Before ocntinuing shall check to add the int(CHR) from the python script…. and rerun all the samples.

###Libraries

library(karyoploteR)
Loading required package: regioneR
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      

Read files

##Load the data
files <- list.files(all.files = TRUE,path = "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti/",
                    pattern = "*.mt.disc.sam.cluster.summary.tsv",
                    recursive = TRUE, 
                    full.names = TRUE)
#Sort the files by the number of output
files <- files[order(nchar(files))]
files
 [1] "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_017_E20_F03/WGS_017_E20_F03.mt.disc.sam.cluster.summary.tsv" "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_021_E20_F02/WGS_021_E20_F02.mt.disc.sam.cluster.summary.tsv"
 [3] "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_024_E20_F02/WGS_024_E20_F02.mt.disc.sam.cluster.summary.tsv" "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_025_E20_F02/WGS_025_E20_F02.mt.disc.sam.cluster.summary.tsv"
 [5] "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_038_E20_F07/WGS_038_E20_F07.mt.disc.sam.cluster.summary.tsv" "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_040_E20_F02/WGS_040_E20_F02.mt.disc.sam.cluster.summary.tsv"
 [7] "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_042_E20_F02/WGS_042_E20_F02.mt.disc.sam.cluster.summary.tsv" "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_043_E20_F02/WGS_043_E20_F02.mt.disc.sam.cluster.summary.tsv"
 [9] "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_047_E20_F02/WGS_047_E20_F02.mt.disc.sam.cluster.summary.tsv" "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_050_E20_F02/WGS_050_E20_F02.mt.disc.sam.cluster.summary.tsv"
[11] "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_050_E20_F03/WGS_050_E20_F03.mt.disc.sam.cluster.summary.tsv" "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_060_E20_F06/WGS_060_E20_F06.mt.disc.sam.cluster.summary.tsv"
[13] "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_063_E20_F02/WGS_063_E20_F02.mt.disc.sam.cluster.summary.tsv" "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_080_E20_F02/WGS_080_E20_F02.mt.disc.sam.cluster.summary.tsv"
[15] "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_084_E20_F02/WGS_084_E20_F02.mt.disc.sam.cluster.summary.tsv" "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_088_E20_F05/WGS_088_E20_F05.mt.disc.sam.cluster.summary.tsv"
[17] "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_088_E20_F06/WGS_088_E20_F06.mt.disc.sam.cluster.summary.tsv" "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_095_E20_F11/WGS_095_E20_F11.mt.disc.sam.cluster.summary.tsv"
[19] "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_115_E20_F03/WGS_115_E20_F03.mt.disc.sam.cluster.summary.tsv" "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_132_E20_F10/WGS_132_E20_F10.mt.disc.sam.cluster.summary.tsv"
[21] "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_134_E20_F02/WGS_134_E20_F02.mt.disc.sam.cluster.summary.tsv" "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_211_E20_F02/WGS_211_E20_F02.mt.disc.sam.cluster.summary.tsv"
[23] "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_220_E20_F07/WGS_220_E20_F07.mt.disc.sam.cluster.summary.tsv" "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_230_E20_F06/WGS_230_E20_F06.mt.disc.sam.cluster.summary.tsv"
[25] "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_240_E20_F05/WGS_240_E20_F05.mt.disc.sam.cluster.summary.tsv" "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_246_E20_F05/WGS_246_E20_F05.mt.disc.sam.cluster.summary.tsv"
[27] "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_246_E20_F07/WGS_246_E20_F07.mt.disc.sam.cluster.summary.tsv" "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_249_E20_F02/WGS_249_E20_F02.mt.disc.sam.cluster.summary.tsv"
[29] "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_252_E20_F02/WGS_252_E20_F02.mt.disc.sam.cluster.summary.tsv" "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_253_E20_F01/WGS_253_E20_F01.mt.disc.sam.cluster.summary.tsv"
[31] "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_262_E20_F07/WGS_262_E20_F07.mt.disc.sam.cluster.summary.tsv" "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_266_E20_F04/WGS_266_E20_F04.mt.disc.sam.cluster.summary.tsv"
[33] "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_289_E20_F02/WGS_289_E20_F02.mt.disc.sam.cluster.summary.tsv" "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_299_E20_F09/WGS_299_E20_F09.mt.disc.sam.cluster.summary.tsv"
[35] "/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_WGS_300_E20_F05/WGS_300_E20_F05.mt.disc.sam.cluster.summary.tsv"
#files
#name_files <- gsub("/home/marius/Documents/Projects/prsa/02_Data/STAR/mapping/release102/","",files)
# name_files <- gsub("D:/PhD/Projects/prsa/02_Data/STAR/mapping/release102/","",files)
name_files <- gsub("/data/botos/2022_12_01_NUMTS_Aedes_Aegypti//NUMTS_OUTPUT_","",
                   gsub(".mt.disc.sam.cluster.summary.tsv","",
                       gsub("WGS.*F[0-9][0-9]*/","",files)))

names(files) <- name_files
#head(files)
#Read it inside lists.
#lapply(names(files),function(x) head(x))
dfs_numts <- lapply(files,function(fj) read.table(fj,header = FALSE))
paste0("List of ",length(dfs_numts)," samples.\n")
[1] "List of 35 samples.\n"
# Split the column into the position data
dfs_numts_pos <- lapply(dfs_numts,function(df) {
  separate(data = df,col = V3,into = c("chr","start","end","MT","mt_start","mt_end"),sep = "_")
})

# add the length of the segment in the chr or mt chromosomes
dfs_numts_pos_match_len <- lapply(dfs_numts_pos,function(df) {
  df <- dplyr::mutate(df,
                      chr_matchLen = as.integer(end) - as.integer(start),
                      mt_matchLen = as.integer(mt_end) - as.integer(mt_start))
  return(df)})

#print

dfs_numts_pos_match_len$WGS_017_E20_F03

Check names


# V5 = Cluster sequences that are in the same cluster 500bp apart gap.
# V6 = cluster of read sequences that are max 500bp apart and mininum 2
lapply(dfs_numts_pos_match_len,function(df) {
  df[["V2"]][1] 
  # names(df)
  # df %>% dplyr::filter(chr %in% c(1,2,3)) %>% dplyr::filter(chr_matchLen > 5 & mt_matchLen > 5) %>%  dplyr::arrange(V6)
  })
$WGS_017_E20_F03
[1] "WGS_017_E20_F03"

$WGS_021_E20_F02
[1] "WGS_021_E20_F02"

$WGS_024_E20_F02
[1] "WGS_024_E20_F02"

$WGS_025_E20_F02
[1] "WGS_025_E20_F02"

$WGS_038_E20_F07
[1] "WGS_038_E20_F07"

$WGS_040_E20_F02
[1] "WGS_040_E20_F02"

$WGS_042_E20_F02
[1] "WGS_042_E20_F02"

$WGS_043_E20_F02
[1] "WGS_043_E20_F02"

$WGS_047_E20_F02
[1] "WGS_047_E20_F02"

$WGS_050_E20_F02
[1] "WGS_050_E20_F02"

$WGS_050_E20_F03
[1] "WGS_050_E20_F03"

$WGS_060_E20_F06
[1] "WGS_060_E20_F06"

$WGS_063_E20_F02
[1] "WGS_063_E20_F02"

$WGS_080_E20_F02
[1] "WGS_080_E20_F02"

$WGS_084_E20_F02
[1] "WGS_084_E20_F02"

$WGS_088_E20_F05
[1] "WGS_088_E20_F05"

$WGS_088_E20_F06
[1] "WGS_088_E20_F06"

$WGS_095_E20_F11
[1] "WGS_095_E20_F11"

$WGS_115_E20_F03
[1] "WGS_115_E20_F03"

$WGS_132_E20_F10
[1] "WGS_132_E20_F10"

$WGS_134_E20_F02
[1] "WGS_134_E20_F02"

$WGS_211_E20_F02
[1] "WGS_211_E20_F02"

$WGS_220_E20_F07
[1] "WGS_220_E20_F07"

$WGS_230_E20_F06
[1] "WGS_230_E20_F06"

$WGS_240_E20_F05
[1] "WGS_240_E20_F05"

$WGS_246_E20_F05
[1] "WGS_246_E20_F05"

$WGS_246_E20_F07
[1] "WGS_246_E20_F07"

$WGS_249_E20_F02
[1] "WGS_249_E20_F02"

$WGS_252_E20_F02
[1] "WGS_252_E20_F02"

$WGS_253_E20_F01
[1] "WGS_253_E20_F01"

$WGS_262_E20_F07
[1] "WGS_262_E20_F07"

$WGS_266_E20_F04
[1] "WGS_266_E20_F04"

$WGS_289_E20_F02
[1] "WGS_289_E20_F02"

$WGS_299_E20_F09
[1] "WGS_299_E20_F09"

$WGS_300_E20_F05
[1] "WGS_300_E20_F05"

###Visualize the data in violins

library(ggplot2)
library(dplyr)
# Iterate over the list of dataframes
plots_df_numts <- lapply(dfs_numts_pos_match_len,function(df){
  # Create the plot
  fig <- ggplot(df  %>% dplyr::group_by(V2) %>% dplyr::filter(chr_matchLen > 5 & mt_matchLen > 5), aes(x=chr_matchLen,y="")) +
    geom_violin(fill="#FAF0E6", alpha=0.4) +
    geom_jitter(aes(color="Nuclear"), size=3, alpha=0.3,show.legend = FALSE) +
    #geom_boxplot(width=0.1) +
    scale_color_manual(values="#000080") +
    # xlim(-30,max(df$chr_matchLen)+30) +
    #xlim(0,1100) +
    scale_x_continuous(breaks = seq(0,1100,100),limits=c(-30,1100)) +
    labs(title=paste0("Nuclear: ",unique(df$V2))) +
    theme(axis.text.y=element_blank(),
          axis.ticks.y=element_blank(),
          axis.title.y = element_blank(),
          plot.background = element_rect(fill = "white"),
          panel.background = element_rect(fill = "white"),
          axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
  
  fig2 <- ggplot( df %>% dplyr::group_by(V2) %>% dplyr::filter(chr_matchLen > 0 & mt_matchLen > 0), aes(x=mt_matchLen,y="")) +
    geom_violin(fill="#FAF0E6", alpha=0.4) +
    geom_jitter(aes(color="Mitochondrial"), size=3, alpha=0.3,show.legend = FALSE) +
    #geom_boxplot(width=0.1) +
    scale_color_manual(values="#800020") +
    # xlim(-30,max(df$mt_matchLen)+30) +
    #xlim(0,12900) +
    scale_x_continuous(breaks = seq(0,12900,500),limits=c(-30,12900)) +
    labs(title=paste0("Mitochondrial: ",unique(df$V2))) +
    theme(axis.text.y=element_blank(),
          axis.ticks.y=element_blank(),
          axis.title.y = element_blank(),
          plot.background = element_rect(fill = "white"),
          panel.background = element_rect(fill = "white"),
          axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
  
  # Print the plot
  print(list(fig,fig2))
  
  # Add the plot to the list
  #plots <- c(plots, list(fig))
  return(plots=list(fig,fig2))
})
[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]

[[1]]

[[2]]


par(mfrow = c(35, 1))#, mar = rep(0.5, 4))
library(gridExtra)
lapply(names(plots_df_numts),function(nm) {
  grid.arrange(grobs=plots_df_numts[[nm]],ncol=2)})
[[1]]
TableGrob (1 x 2) "arrange": 2 grobs

[[2]]
TableGrob (1 x 2) "arrange": 2 grobs

[[3]]
TableGrob (1 x 2) "arrange": 2 grobs

[[4]]
TableGrob (1 x 2) "arrange": 2 grobs

[[5]]
TableGrob (1 x 2) "arrange": 2 grobs

[[6]]
TableGrob (1 x 2) "arrange": 2 grobs

[[7]]
TableGrob (1 x 2) "arrange": 2 grobs

[[8]]
TableGrob (1 x 2) "arrange": 2 grobs

[[9]]
TableGrob (1 x 2) "arrange": 2 grobs

[[10]]
TableGrob (1 x 2) "arrange": 2 grobs

[[11]]
TableGrob (1 x 2) "arrange": 2 grobs

[[12]]
TableGrob (1 x 2) "arrange": 2 grobs

[[13]]
TableGrob (1 x 2) "arrange": 2 grobs

[[14]]
TableGrob (1 x 2) "arrange": 2 grobs

[[15]]
TableGrob (1 x 2) "arrange": 2 grobs

[[16]]
TableGrob (1 x 2) "arrange": 2 grobs

[[17]]
TableGrob (1 x 2) "arrange": 2 grobs

[[18]]
TableGrob (1 x 2) "arrange": 2 grobs

[[19]]
TableGrob (1 x 2) "arrange": 2 grobs

[[20]]
TableGrob (1 x 2) "arrange": 2 grobs

[[21]]
TableGrob (1 x 2) "arrange": 2 grobs

[[22]]
TableGrob (1 x 2) "arrange": 2 grobs

[[23]]
TableGrob (1 x 2) "arrange": 2 grobs

[[24]]
TableGrob (1 x 2) "arrange": 2 grobs

[[25]]
TableGrob (1 x 2) "arrange": 2 grobs

[[26]]
TableGrob (1 x 2) "arrange": 2 grobs

[[27]]
TableGrob (1 x 2) "arrange": 2 grobs

[[28]]
TableGrob (1 x 2) "arrange": 2 grobs

[[29]]
TableGrob (1 x 2) "arrange": 2 grobs

[[30]]
TableGrob (1 x 2) "arrange": 2 grobs

[[31]]
TableGrob (1 x 2) "arrange": 2 grobs

[[32]]
TableGrob (1 x 2) "arrange": 2 grobs

[[33]]
TableGrob (1 x 2) "arrange": 2 grobs

[[34]]
TableGrob (1 x 2) "arrange": 2 grobs

[[35]]
TableGrob (1 x 2) "arrange": 2 grobs
NA

NA

Filter numts that are not 0 in the MT or the CHR and show how many numts per RIL. (inlcude maybe the clustering of the numts later)

lapply(dfs_numts_pos_match_len,function(df) {
  df %>% dplyr::group_by(V2) %>% dplyr::filter(chr %in% c(1,2,3)) %>% dplyr::filter(chr_matchLen > 20 & mt_matchLen > 20) %>% dplyr::summarise(n=n())})
$WGS_017_E20_F03

$WGS_021_E20_F02

$WGS_024_E20_F02

$WGS_025_E20_F02

$WGS_038_E20_F07

$WGS_040_E20_F02

$WGS_042_E20_F02

$WGS_043_E20_F02

$WGS_047_E20_F02

$WGS_050_E20_F02

$WGS_050_E20_F03

$WGS_060_E20_F06

$WGS_063_E20_F02

$WGS_080_E20_F02

$WGS_084_E20_F02

$WGS_088_E20_F05

$WGS_088_E20_F06

$WGS_095_E20_F11

$WGS_115_E20_F03

$WGS_132_E20_F10

$WGS_134_E20_F02

$WGS_211_E20_F02

$WGS_220_E20_F07

$WGS_230_E20_F06

$WGS_240_E20_F05

$WGS_246_E20_F05

$WGS_246_E20_F07

$WGS_249_E20_F02

$WGS_252_E20_F02

$WGS_253_E20_F01

$WGS_262_E20_F07

$WGS_266_E20_F04

$WGS_289_E20_F02

$WGS_299_E20_F09

$WGS_300_E20_F05
NA

List of Samples and number of numts per sample in the Chr 1,2,3

# counts_of_numts_longer_than_20bp <- lapply(dfs_numts_pos_match_len,function(df) {
#   df %>% dplyr::group_by(V2) %>% dplyr::filter(chr %in% c(1,2,3)) %>% dplyr::filter(chr_matchLen > 20 & mt_matchLen > 20) %>% dplyr::summarise(n=n())})
# 

counts_of_numts_longer_than_20bp <- lapply(dfs_numts_pos_match_len,function(df) df %>% dplyr::filter(chr %in% c(1,2,3)) %>% dplyr::filter(chr_matchLen > 20 & mt_matchLen > 20)   %>% dplyr::mutate_at(c("mt_start","mt_end","mt_matchLen"),as.numeric) %>% group_by(group = cut(mt_matchLen, breaks = seq(0,17000,50))) %>% summarize(mt_matchLen = n(),sampleID = df[[2]][1]))

counts_of_numts_longer_than_20bp_df <- do.call(rbind,counts_of_numts_longer_than_20bp)

#dir.create("/home/botos/SVRAW1/botos/2023_02_08_NUMTS/final_numts/Table",recursive = TRUE)

write.table(counts_of_numts_longer_than_20bp_df,file = "/home/botos/SVRAW1/botos/2023_02_08_NUMTS/final_numts/Table/numts_ranges_all_samples.csv",sep = ",")
p <- counts_of_numts_longer_than_20bp_df %>% ggplot(aes(x=as.factor(group), y=mt_matchLen,fill = ("red"))) +
  geom_col(alpha=0.7) +
  #geom_col(data= dataT[1:39,],mapping = aes(x=date,y=income/2 ,fill=d1)) +
  geom_line(data= counts_of_numts_longer_than_20bp_df,group=1,mapping=aes(x=as.factor(group),y=mt_matchLen)) +
  # geom_point(data = counts_of_numts_longer_than_20bp_df,
  #            aes(x = counts_of_numts_longer_than_20bp_df$group[which.max(counts_of_numts_longer_than_20bp_df$mt_matchLen)],
  #                y = counts_of_numts_longer_than_20bp_df$mt_matchLen[which.max(counts_of_numts_longer_than_20bp_df$mt_matchLen)]), color="black",size=3) +
  #geom_area(position = "identity", alpha = 0.5,color="red") +
  #geom_bar(stat = "identity") +
  #stat_density(aes(geom="line",position="identity")) + 
  #geom_density(aes(after_stat(count))) +
  #xlim(c(0,17000)) +
  #coord_flip() +
  labs(fill = "Numts Length Group") +
  scale_x_discrete("group") +
  facet_wrap(~sampleID,ncol = 2) +
  theme(axis.text.x = element_text(angle = 90, hjust = 1)) 

p

svg(filename = "/home/botos/SVRAW1/botos/2023_02_08_NUMTS/final_numts/Plots/numts_ranges_all_samples_barplots_per_sample.svg",
    width = 16,
    height = 31)
p
dev.off()
png 
  2 

Genes for circos

###add mt genes
mt_genes_ae <- read.table(file = "/home/botos/SVRAW1/botos/2023_02_08_NUMTS/Visualization_samples/mt_ae_gtf_genes_trna_rrna.txt",sep = "\t")
 
# unique(mt_genes_ae$V5) 
# unique(mt_genes_ae$V6) 
# unique(mt_genes_ae$V7)
# unique(mt_genes_ae$V4) 

mt_genes_ae$paste <- paste(mt_genes_ae$V5,mt_genes_ae$V6,sep="_")
mt_genes_ae <- mt_genes_ae[,c("V2","V3","paste")]
mt_genes_ae <- mt_genes_ae %>% dplyr::filter(paste != "_") %>% dplyr::mutate(Genes= str_remove(paste,"^_|_$"))
mt_genes_ae <- mt_genes_ae[,c("V2","V3","Genes")]
mt_genes_ae$chr <- "chrM"
mt_genes_ae$value <- 1
mt_genes_ae <- mt_genes_ae[,c("chr","V2","V3","value","Genes")]
colnames(mt_genes_ae) <- c("chr","start","end","value","gene")
mt_genes_ae$start <- mt_genes_ae$start * 100000
mt_genes_ae$end <- mt_genes_ae$end * 100000
mt_genes_ae <- mt_genes_ae %>% dplyr::mutate_at(c("start","end","value"),as.numeric)

# chr_genes_ae <- df1_link_WGS_017_E20_F03
# chr_genes_ae$gene <- "Ecxample.2.1aa.2"

# anno_genes_ae <- rbind(mt_genes_ae,chr_genes_ae)
# 
# anno_genes_ae <- anno_genes_ae %>% dplyr::mutate_at(c("start","end","value"),as.numeric)

# run and commennt and re runn the one on top
mt_genes_ae <- read.table(file = "/home/botos/SVRAW1/botos/2023_02_08_NUMTS/Visualization_samples/mt_ae_gtf_genes_trna_rrna.txt",sep = "\t")
mt_genes_2 <- mt_genes_ae %>% dplyr::filter(V1 == "gene") %>% dplyr::select(V2,V3,V6) %>% dplyr::filter(V6 != "") %>% dplyr::mutate(chr="chrM",
                                                                                                                                    value = 1)
mt_genes_2 <- mt_genes_2[,c("chr","V2","V3","value","V6")]
colnames(mt_genes_2) <- c("chr","start","end","value","gene")
mt_genes_2$start <- mt_genes_2$start * 100000
mt_genes_2$end <- mt_genes_2$end * 100000
mt_genes_2 <- mt_genes_2 %>% dplyr::mutate_at(c("start","end","value"),as.numeric)

Apply circos for all samples

circos_RIL_plots <- lapply(dfs_numts_pos_match_len,function(df) {
  
  #png(filename = paste0("/home/botos/SVRAW1/botos/2023_02_08_NUMTS/final_numts/Plots/",df[["V2"]][1],"_circos_chr_to_mt.png"),width = 680,height = 680)
  #svg(filename = paste0("/home/botos/SVRAW1/botos/2023_02_08_NUMTS/final_numts/Plots/",df[["V2"]][1],"_circos_chr_to_mt.svg"),width = 10,height = 10)

  
  #run code for circos
  df_s <- df %>% dplyr::group_by(chr) %>%
    dplyr::filter(chr_matchLen > 20 & mt_matchLen > 20) %>%
    dplyr::arrange(V6) %>% 
    dplyr::select(chr,start,end,chr_matchLen,mt_start,mt_end,mt_matchLen) %>%
    dplyr::distinct()
  
  df_s$mt_start <- as.integer(df_s$mt_start)*100000
  df_s$mt_end <- as.integer(df_s$mt_end)*100000
  
  chr_df_s <- df_s %>% dplyr::filter(chr %in% c(1,2,3)) %>% dplyr::select(chr,start,end,chr_matchLen) %>% dplyr::mutate(chr=paste0("chr",chr))
  colnames(chr_df_s) <- c("chr","start","end","value")
  mt_df_s <- df_s %>% dplyr::filter(chr %in% c(1,2,3)) %>% dplyr::select(mt_start,mt_end,mt_matchLen)
  mt_df_s$chr <- "chrM"
  colnames(mt_df_s) <- c("chr","start","end","value")

  chr_df_s$start <- as.integer(chr_df_s$start)
  chr_df_s$end <- as.integer(chr_df_s$end)
  chr_mt_df_s <- dplyr::bind_rows(chr_df_s,mt_df_s)
  
  #Create the chr and mt regions of the numts by splitting them.

  df1_link <- chr_mt_df_s %>% dplyr::filter(chr %in% c("chr1","chr2","chr3"))
  df2_link <- chr_mt_df_s %>% dplyr::filter(chr %in% c("chrM")) 
  
  
  
  # Plot the circos
  #circos.par("track.height"=0.8, gap.degree=5, cell.padding=c(0, 0, 0, 0))
  circos.clear()
  circos.par(gap.degree=5)

  ref_fd_ae <- data.frame("Chromosome"=c("chr1","chr2","chr3","chrM"),"ChromStart"=c(0,0,0,0),"Chromend"=c(310827022,474425716,409777670,16790*100000))

  #circos.genomicInitialize(ref_fd_ae)
  circos.genomicInitialize(ref_fd_ae,plotType = NULL)
  circos.genomicLabels(mt_genes_ae ,labels.column = 5, cex=0.7,line_lwd=0.6, line_col="grey20", connection_height = 0.019,
                       labels_height = 0.2,niceFacing = TRUE,side = "outside")
  # circos.genomicLabels(mt_genes_2 ,labels.column = 5, cex=0.5,line_lwd=0.6, line_col="grey20", connection_height = 0.05, labels_height = 0.2,niceFacing = TRUE,side = "outside")

  circos.track(ylim=c(0, 1), panel.fun=function(x, y) {
    chr=CELL_META$sector.index
    xlim=CELL_META$xlim
    ylim=CELL_META$ylim
    circos.text(mean(xlim), mean(ylim), chr, cex=0.8)}, bg.col = c("#0000FF40","#0000FF40","#0000FF40","#FF000040"), bg.border=F, track.height=0.06)
  
  circos.track(track.index = get.current.track.index(),
               panel.fun = function(x, y) {
                 circos.genomicAxis(h = "bottom", direction = "inside",labels.cex = 0.6,tickLabelsStartFromZero = TRUE)})
  
  set_track_gap(gap = 0.04)
  
  # circos.genomicTrack(chr_mt_df_s %>% dplyr::distinct(),
  #                     track.height=0.1,
  #                     panel.fun = function(region, value, ...) {
  #                       circos.genomicPoints(region, value,
  #                                            pch = 6,
  #                                            cex = 1.6,
  #                                            col="black")})#col=ifelse(value[[1]] > 150,"red","black"))})
  circos.genomicTrack(chr_mt_df_s %>% dplyr::distinct(),
                      track.height=0.2,
                      panel.fun = function(region,value,...) {
                        circos.genomicRect(region, value,col = "#FF000040",...)})
                        #circos.genomicPoints(region, value,pch = 6,cex = 1.6,col="black")})#col=ifelse(value[[1]] > 150,"red","black"))})
  

  
  #circos.update(sector.index = "chrM",track.index = 4)
  #circos.points(x=col="red")
  
  col <- alpha(wes_palette("Zissou1", n = nrow(df2_link), type = "continuous"), 0.4)
  circos.genomicLink(df1_link %>%  dplyr::mutate_at(c("start","end","value"),as.numeric),
                     df2_link %>%  dplyr::mutate_at(c("start","end","value"),as.numeric),
                     #use lirbary wesanderson http://www.sthda.com/english/wiki/colors-in-r
                     col = col)
  # col = colorRampPalette(brewer.pal(5, "Dark2"))(nrow(df2_link_WGS_017_E20_F03)))#,border = NA,transparency=0.1)
  title(paste0(df[["V2"]][1]))
 # dev.off()

})
Adding missing grouping variables: `chr`
Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

Adding missing grouping variables: `chr`

save the table of the plots


#v5 is cluster of 500bp gaps
#v6 is cluster of more than 2 reads supporting the previous cluster
lapply(dfs_numts_pos_match_len,function(df) {
  df_s <- df %>% dplyr::group_by(chr) %>%
    dplyr::filter(chr_matchLen > 20 & mt_matchLen > 20) %>%
    dplyr::arrange(V6) %>% 
    dplyr::select(chr,start,end,chr_matchLen,mt_start,mt_end,mt_matchLen) %>%
    dplyr::distinct() %>% 
    write.table(paste0("/home/botos/SVRAW1/botos/2023_02_08_NUMTS/final_numts/Table/",df[["V2"]][1],"_chr_to_mt_table.csv"),sep = ",",col.names = TRUE,row.names = FALSE)
})
$WGS_017_E20_F03
NULL

$WGS_021_E20_F02
NULL

$WGS_024_E20_F02
NULL

$WGS_025_E20_F02
NULL

$WGS_038_E20_F07
NULL

$WGS_040_E20_F02
NULL

$WGS_042_E20_F02
NULL

$WGS_043_E20_F02
NULL

$WGS_047_E20_F02
NULL

$WGS_050_E20_F02
NULL

$WGS_050_E20_F03
NULL

$WGS_060_E20_F06
NULL

$WGS_063_E20_F02
NULL

$WGS_080_E20_F02
NULL

$WGS_084_E20_F02
NULL

$WGS_088_E20_F05
NULL

$WGS_088_E20_F06
NULL

$WGS_095_E20_F11
NULL

$WGS_115_E20_F03
NULL

$WGS_132_E20_F10
NULL

$WGS_134_E20_F02
NULL

$WGS_211_E20_F02
NULL

$WGS_220_E20_F07
NULL

$WGS_230_E20_F06
NULL

$WGS_240_E20_F05
NULL

$WGS_246_E20_F05
NULL

$WGS_246_E20_F07
NULL

$WGS_249_E20_F02
NULL

$WGS_252_E20_F02
NULL

$WGS_253_E20_F01
NULL

$WGS_262_E20_F07
NULL

$WGS_266_E20_F04
NULL

$WGS_289_E20_F02
NULL

$WGS_299_E20_F09
NULL

$WGS_300_E20_F05
NULL

karyotype plotter

mt_genes_2_ranges
GRanges object with 13 ranges and 3 metadata columns:
          seqnames      ranges strand |       genes        y0        y1
             <Rle>   <IRanges>  <Rle> | <character> <numeric> <numeric>
   [1] NC_035159.1     70-1095      * |         ND2         0      0.13
   [2] NC_035159.1   1298-2834      * |        COX1         0      0.13
   [3] NC_035159.1   2903-3587      * |        COX2         0      0.13
   [4] NC_035159.1   3744-3905      * |        ATP8         0      0.13
   [5] NC_035159.1   3899-4579      * |        ATP6         0      0.13
   ...         ...         ...    ... .         ...       ...       ...
   [9] NC_035159.1   8027-9370      * |         ND4         0      0.13
  [10] NC_035159.1   9364-9660      * |        ND4L         0      0.13
  [11] NC_035159.1  9798-10319      * |         ND6         0      0.13
  [12] NC_035159.1 10323-11457      * |        CYTB         0      0.13
  [13] NC_035159.1 11547-12488      * |         ND1         0      0.13
  -------
  seqinfo: 1 sequence from an unspecified genome; no seqlengths
Wrangle for each sample the genomic rannges
library(S4Vectors)
library(GenomicRanges)
library(IRanges)
library(karyoploteR)

list_of_regions <- lapply(dfs_numts_pos_match_len,function(df){
  
  cat(paste0("start with sample: ",df[["V2"]][1],"\n"))
  ranges_df <- GRanges(seqnames = df %>% dplyr::filter(chr_matchLen > 20 & mt_matchLen > 20) %>% dplyr::filter(chr %in% c(1,2,3)) %>% dplyr::pull(chr),
                       ranges =IRanges(start = as.numeric(df %>% dplyr::filter(chr_matchLen > 20 & mt_matchLen > 20) %>%
                                                            dplyr::filter(chr %in% c(1,2,3)) %>%
                                                            dplyr::pull(mt_start)),
                                       end = as.numeric(df %>% dplyr::filter(chr_matchLen > 20 & mt_matchLen > 20) %>%
                                                          dplyr::filter(chr %in% c(1,2,3)) %>%
                                                          dplyr::pull(mt_end))),
                       real_chr="chrM")
  
  ranges_df <- as.data.frame(ranges_df)
  ranges_df$seqnames2 <- ranges_df$seqnames
  #Set the name of the chrm to the official ncbi nane that i use to create under the genes for overlapping.
  #ranges_df$seqnames <- "chrM"
  ranges_df$seqnames <- "NC_035159.1"
  ranges_df <- dplyr::mutate(ranges_df,
                             chr_start_end=paste0(seqnames,":",start,"-",end))
  
  cat("extracting regions\n")
  empty_gr <- GRanges(seqnames = character(), IRanges(start = integer(), end = integer()))
  
  regs1 <- if(nrow(ranges_df %>% dplyr::filter(seqnames2 == 1)) != 0){
    toGRanges(ranges_df %>% filter(seqnames2 == 1) %>% dplyr::pull(chr_start_end))
  }else{
  empty_gr}
  
  regs2 <- if(nrow(ranges_df %>% dplyr::filter(seqnames2 == 2)) != 0){
    toGRanges(ranges_df %>% filter(seqnames2 == 2) %>% dplyr::pull(chr_start_end))
  }else{
  empty_gr}
  
  regs3 <- if(nrow(ranges_df %>% dplyr::filter(seqnames2 == 3)) != 0){
    toGRanges(ranges_df %>% filter(seqnames2 == 3) %>% dplyr::pull(chr_start_end))
  }else{
  empty_gr}
  
  regs1_df <- as.data.frame(regs1) %>% dplyr::mutate(chrom="chr1")
  regs2_df <- as.data.frame(regs2) %>% dplyr::mutate(chrom="chr2")
  regs3_df <- as.data.frame(regs3) %>% dplyr::mutate(chrom="chr3")
  regs_df <- rbind(regs1_df,regs2_df,regs3_df)
  cat("done\n")
  return(regs_df)})
start with sample: WGS_017_E20_F03
extracting regions
done
start with sample: WGS_021_E20_F02
extracting regions
done
start with sample: WGS_024_E20_F02
extracting regions
done
start with sample: WGS_025_E20_F02
extracting regions
done
start with sample: WGS_038_E20_F07
extracting regions
done
start with sample: WGS_040_E20_F02
extracting regions
done
start with sample: WGS_042_E20_F02
extracting regions
done
start with sample: WGS_043_E20_F02
extracting regions
done
start with sample: WGS_047_E20_F02
extracting regions
done
start with sample: WGS_050_E20_F02
extracting regions
done
start with sample: WGS_050_E20_F03
extracting regions
done
start with sample: WGS_060_E20_F06
extracting regions
done
start with sample: WGS_063_E20_F02
extracting regions
done
start with sample: WGS_080_E20_F02
extracting regions
done
start with sample: WGS_084_E20_F02
extracting regions
done
start with sample: WGS_088_E20_F05
extracting regions
done
start with sample: WGS_088_E20_F06
extracting regions
done
start with sample: WGS_095_E20_F11
extracting regions
done
start with sample: WGS_115_E20_F03
extracting regions
done
start with sample: WGS_132_E20_F10
extracting regions
done
start with sample: WGS_134_E20_F02
extracting regions
done
start with sample: WGS_211_E20_F02
extracting regions
done
start with sample: WGS_220_E20_F07
extracting regions
done
start with sample: WGS_230_E20_F06
extracting regions
done
start with sample: WGS_240_E20_F05
extracting regions
done
start with sample: WGS_246_E20_F05
extracting regions
done
start with sample: WGS_246_E20_F07
extracting regions
done
start with sample: WGS_249_E20_F02
extracting regions
done
start with sample: WGS_252_E20_F02
extracting regions
done
start with sample: WGS_253_E20_F01
extracting regions
done
start with sample: WGS_262_E20_F07
extracting regions
done
start with sample: WGS_266_E20_F04
extracting regions
done
start with sample: WGS_289_E20_F02
extracting regions
done
start with sample: WGS_299_E20_F09
extracting regions
done
start with sample: WGS_300_E20_F05
extracting regions
done
library(S4Vectors)



lapply(names(list_of_regions),function(kt){
  
  #svg(filename = paste0("/home/botos/SVRAW1/botos/2023_02_08_NUMTS/final_numts/Plots/karytypePlot_",kt,"numts_chr.svg"),width = 12,height = 4)
  
  custom.genome <- toGRanges(data.frame(chr=c("NC_035159.1"),start=c(0),end=c(16790)))
  kp <- plotKaryotype(genome = custom.genome)
  kpDataBackground(kp, r0 = 0,r1 = 0.25)
  kpDataBackground(kp, r0 = 0.25,r1 = 0.5,col="#FF000040")
  kpDataBackground(kp, r0 = 0.5,r1 = 0.75,col="#FF000040")
  kpDataBackground(kp, r0 = 0.75,r1 = 1,col="#FF000040")
  
  
   
  
  
  kpRect(kp,mt_genes_2_ranges,col="red")
  kpText(karyoplot = kp,data = mt_genes_2_ranges,labels = mt_genes_2_ranges$genes,y = 0.17,cex=0.6,col="red")
  
  #add mt sequences from  each chromoosome
  #add numts from chr 1
  kpRect(kp,data = list_of_regions[[kt]] %>% filter(chrom == "chr1") %>% toGRanges, y0 = 0.3,y1=0.4) 
  #add numts from chr 2
  kpRect(kp,data = list_of_regions[[kt]] %>% filter(chrom == "chr2") %>% toGRanges, y0 = 0.6,y1 = 0.7)
  #add numts from chr 3
  kpRect(kp,data = list_of_regions[[kt]] %>% filter(chrom == "chr3") %>% toGRanges, y0 = 0.8,y1 = 0.9)
  title(paste0(kt))
  
  #dev.off()
    
})

[[1]]
NULL

[[2]]
NULL

[[3]]
NULL

[[4]]
NULL

[[5]]
NULL

[[6]]
NULL

[[7]]
NULL

[[8]]
NULL

[[9]]
NULL

[[10]]
NULL

[[11]]
NULL

[[12]]
NULL

[[13]]
NULL

[[14]]
NULL

[[15]]
NULL

[[16]]
NULL

[[17]]
NULL

[[18]]
NULL

[[19]]
NULL

[[20]]
NULL

[[21]]
NULL

[[22]]
NULL

[[23]]
NULL

[[24]]
NULL

[[25]]
NULL

[[26]]
NULL

[[27]]
NULL

[[28]]
NULL

[[29]]
NULL

[[30]]
NULL

[[31]]
NULL

[[32]]
NULL

[[33]]
NULL

[[34]]
NULL

[[35]]
NULL

Counnt overlaps by sample and all together and plot CIRCOS

Per sample

result_lists_aaeg_genes_hit_with_symbol_counts
$WGS_017_E20_F03

$WGS_021_E20_F02

$WGS_024_E20_F02

$WGS_025_E20_F02

$WGS_038_E20_F07

$WGS_040_E20_F02

$WGS_042_E20_F02

$WGS_043_E20_F02

$WGS_047_E20_F02

$WGS_050_E20_F02

$WGS_050_E20_F03

$WGS_060_E20_F06

$WGS_063_E20_F02

$WGS_080_E20_F02

$WGS_084_E20_F02

$WGS_088_E20_F05

$WGS_088_E20_F06

$WGS_095_E20_F11

$WGS_115_E20_F03

$WGS_132_E20_F10

$WGS_134_E20_F02

$WGS_211_E20_F02

$WGS_220_E20_F07

$WGS_230_E20_F06

$WGS_240_E20_F05

$WGS_246_E20_F05

$WGS_246_E20_F07

$WGS_249_E20_F02

$WGS_252_E20_F02

$WGS_253_E20_F01

$WGS_262_E20_F07

$WGS_266_E20_F04

$WGS_289_E20_F02

$WGS_299_E20_F09

$WGS_300_E20_F05
NA

mtDNA numts circos per sample


#mm="WGS_088_E20_F05"
# result_lists_aaeg_genes_hit_with_symbol_counts[[""]]

lapply(names(result_lists_aaeg_genes_hit_with_symbol_counts),function(mm) {
  print(paste0("plotting for sample", mm))
  
  #png(filename = paste0("/home/botos/SVRAW1/botos/2023_02_08_NUMTS/Visualization_samples/R_CIRCOS_RIL/",df[["V2"]][1],".png"),width = 680,height = 680)
  #svg(filename = paste0("/home/botos/SVRAW1/botos/2023_02_08_NUMTS/final_numts/Plots/RIL_mtDNA_overlap_numts_",mm,"_circos.svg"),width = 9,height = 9)
  
  
  mt_genes_ae_2 <- mt_genes_ae
  mt_genes_ae_2$start <- mt_genes_ae_2$start/100000
  mt_genes_ae_2$end <- mt_genes_ae_2$end/100000


  numts_hits_df_merged_counted_start_end <- mt_genes_ae_2 %>% dplyr::select(chr,start,end,gene) %>%
    dplyr::right_join(result_lists_aaeg_genes_hit_with_symbol_counts[[mm]],by = c("gene"="symbol")) %>%
    dplyr::mutate(value=col2_sum) %>%
    dplyr::select(chr,start,end,value,gene) %>%
    dplyr::arrange(start,end)
  
  
  numts_hits_df_merged_counted_start_end$value_scaled <- numts_hits_df_merged_counted_start_end$value/10

  
  
  library(circlize)
  ref_fd_ae <- data.frame("Chromosome"=c("chrM"),"ChromStart"=c(1),"Chromend"=c(16790))
  #circos.genomicInitialize(ref_fd_ae)
  circos.genomicInitialize(ref_fd_ae,plotType = NULL)
  circos.genomicLabels(mt_genes_ae_2 ,
                       labels.column = 5,
                       cex=0.7,line_lwd=0.6, line_col="grey20",
                       connection_height = 0.019,
                       col=ifelse(mt_genes_ae_2$gene %in% numts_hits_df_merged_counted_start_end$gene[numts_hits_df_merged_counted_start_end$value_scaled > mean(numts_hits_df_merged_counted_start_end$value_scaled)],"red","black"),
                       labels_height = 0.2,niceFacing = TRUE,side = "outside")
  
  
  # circos.genomicLabels(mt_genes_2 ,labels.column = 5, cex=0.5,line_lwd=0.6, line_col="grey20", connection_height = 0.05, labels_height = 0.2,niceFacing = TRUE,side = "outside")

  circos.track(ylim=c(0, 1), panel.fun=function(x, y) {
  chr=CELL_META$sector.index
  xlim=CELL_META$xlim
  ylim=CELL_META$ylim#
  circos.text(mean(xlim), mean(ylim), chr, cex=0.8)}, bg.col = c("white"), bg.border=F, track.height=0.2) # the track height of the text specifies how thick is the track were we plot the bars
  
  circos.track(track.index = get.current.track.index(),
               track.height=0.8,
               ylim=c(0,1), #this track y lim specifies how big are the bars up to in the track y lim 
               panel.fun = function(x, y) {
                 circos.genomicAxis(h = "bottom", direction = "inside",labels.cex = 0.6,tickLabelsStartFromZero = FALSE)})
  # set_track_gap(gap = 0.05)
  
  
  # ddff <- mt_genes_ae_2 %>% dplyr::select(chr,start,end,gene) %>% dplyr::right_join(result_lists_aaeg_genes_hit_with_symbol_counts$WGS_211_E20_F02,by = c("gene"="symbol")) %>%dplyr::mutate(value=col2_sum) %>% dplyr::select(chr,start,end,value,gene) %>% dplyr::arrange(start,end)
# 
  # ddff_2 <- mt_genes_ae_2 %>% dplyr::select(chr,start,end,gene) %>% dplyr::right_join(result_lists_aaeg_genes_hit_with_symbol_counts$WGS_038_E20_F07,by = c("gene"="symbol")) %>% dplyr::mutate(value=col2_sum) %>% dplyr::select(chr,start,end,value,gene) %>% dplyr::arrange(start,end)


  library(RColorBrewer)
  green_pal <- colorRampPalette(brewer.pal(9, "Greens"))

 
  map_value_to_color <- function(value) {
    breaks <- seq(0,8,0.9)
    colors <- green_pal(9)
    colors[findInterval(value, breaks)]
  }
  
  circos.rect(xleft = numts_hits_df_merged_counted_start_end$start,
              ybottom = 0.01,
              xright = numts_hits_df_merged_counted_start_end$end,
              ytop = 0.02 + numts_hits_df_merged_counted_start_end$value_scaled,
              #col = rgb(0.4, 0.7, 0.4, alpha = 0.5),
              #col = ("#95D5B2"),
              col = map_value_to_color(numts_hits_df_merged_counted_start_end$value_scaled),
              #col = my_colors_scaled,
              border = "black")
  #circos.lines(CELL_META$cell.xlim, c(max(numts_hits_df_merged_counted_start_end$value_scaled)+0.02, max(numts_hits_df_merged_counted_start_end$value_scaled)+0.2),lwd = 2, lty = 2, col = "#A71246")
  #circos.lines(CELL_META$cell.xlim, c(min(numts_hits_df_merged_counted_start_end$value)+5, min(numts_hits_df_merged_counted_start_end$value)+5),lwd = 2, lty = 2, col = "blue")
  circos.lines(CELL_META$cell.xlim, c(mean(numts_hits_df_merged_counted_start_end$value_scaled)+0.01, mean(numts_hits_df_merged_counted_start_end$value_scaled)+0.01),lwd = 2, lty = 2, col = "#03071E")
  
  
  
  #dev.off()
  #result_lists_aaeg_genes_hit_with_symbol_counts[[mm]]
})
[1] "plotting for sampleWGS_017_E20_F03"
[1] "plotting for sampleWGS_021_E20_F02"

[1] "plotting for sampleWGS_024_E20_F02"

[1] "plotting for sampleWGS_025_E20_F02"

[1] "plotting for sampleWGS_038_E20_F07"

[1] "plotting for sampleWGS_040_E20_F02"

[1] "plotting for sampleWGS_042_E20_F02"

[1] "plotting for sampleWGS_043_E20_F02"

[1] "plotting for sampleWGS_047_E20_F02"

[1] "plotting for sampleWGS_050_E20_F02"

[1] "plotting for sampleWGS_050_E20_F03"

[1] "plotting for sampleWGS_060_E20_F06"

[1] "plotting for sampleWGS_063_E20_F02"

[1] "plotting for sampleWGS_080_E20_F02"

[1] "plotting for sampleWGS_084_E20_F02"

[1] "plotting for sampleWGS_088_E20_F05"

[1] "plotting for sampleWGS_088_E20_F06"

[1] "plotting for sampleWGS_095_E20_F11"

[1] "plotting for sampleWGS_115_E20_F03"

[1] "plotting for sampleWGS_132_E20_F10"

[1] "plotting for sampleWGS_134_E20_F02"

[1] "plotting for sampleWGS_211_E20_F02"

[1] "plotting for sampleWGS_220_E20_F07"

[1] "plotting for sampleWGS_230_E20_F06"

[1] "plotting for sampleWGS_240_E20_F05"

[1] "plotting for sampleWGS_246_E20_F05"

[1] "plotting for sampleWGS_246_E20_F07"

[1] "plotting for sampleWGS_249_E20_F02"

[1] "plotting for sampleWGS_252_E20_F02"

[1] "plotting for sampleWGS_253_E20_F01"

[1] "plotting for sampleWGS_262_E20_F07"

[1] "plotting for sampleWGS_266_E20_F04"

[1] "plotting for sampleWGS_289_E20_F02"

[1] "plotting for sampleWGS_299_E20_F09"

[1] "plotting for sampleWGS_300_E20_F05"

[[1]]
NULL

[[2]]
NULL

[[3]]
NULL

[[4]]
NULL

[[5]]
NULL

[[6]]
NULL

[[7]]
NULL

[[8]]
NULL

[[9]]
NULL

[[10]]
NULL

[[11]]
NULL

[[12]]
NULL

[[13]]
NULL

[[14]]
NULL

[[15]]
NULL

[[16]]
NULL

[[17]]
NULL

[[18]]
NULL

[[19]]
NULL

[[20]]
NULL

[[21]]
NULL

[[22]]
NULL

[[23]]
NULL

[[24]]
NULL

[[25]]
NULL

[[26]]
NULL

[[27]]
NULL

[[28]]
NULL

[[29]]
NULL

[[30]]
NULL

[[31]]
NULL

[[32]]
NULL

[[33]]
NULL

[[34]]
NULL

[[35]]
NULL

lapply(names(result_lists_aaeg_genes_hit_with_symbol_counts),function(mm) {
  print(paste0("saved sample", mm))
  write.table(x = result_lists_aaeg_genes_hit_with_symbol_counts[[mm]],
              file = paste0("/home/botos/SVRAW1/botos/2023_02_08_NUMTS/final_numts/Table/RIL_mtDNA_overlap_numts_",mm,"_circos_table.csv"),sep = ",")})
[1] "saved sampleWGS_017_E20_F03"
[1] "saved sampleWGS_021_E20_F02"
[1] "saved sampleWGS_024_E20_F02"
[1] "saved sampleWGS_025_E20_F02"
[1] "saved sampleWGS_038_E20_F07"
[1] "saved sampleWGS_040_E20_F02"
[1] "saved sampleWGS_042_E20_F02"
[1] "saved sampleWGS_043_E20_F02"
[1] "saved sampleWGS_047_E20_F02"
[1] "saved sampleWGS_050_E20_F02"
[1] "saved sampleWGS_050_E20_F03"
[1] "saved sampleWGS_060_E20_F06"
[1] "saved sampleWGS_063_E20_F02"
[1] "saved sampleWGS_080_E20_F02"
[1] "saved sampleWGS_084_E20_F02"
[1] "saved sampleWGS_088_E20_F05"
[1] "saved sampleWGS_088_E20_F06"
[1] "saved sampleWGS_095_E20_F11"
[1] "saved sampleWGS_115_E20_F03"
[1] "saved sampleWGS_132_E20_F10"
[1] "saved sampleWGS_134_E20_F02"
[1] "saved sampleWGS_211_E20_F02"
[1] "saved sampleWGS_220_E20_F07"
[1] "saved sampleWGS_230_E20_F06"
[1] "saved sampleWGS_240_E20_F05"
[1] "saved sampleWGS_246_E20_F05"
[1] "saved sampleWGS_246_E20_F07"
[1] "saved sampleWGS_249_E20_F02"
[1] "saved sampleWGS_252_E20_F02"
[1] "saved sampleWGS_253_E20_F01"
[1] "saved sampleWGS_262_E20_F07"
[1] "saved sampleWGS_266_E20_F04"
[1] "saved sampleWGS_289_E20_F02"
[1] "saved sampleWGS_299_E20_F09"
[1] "saved sampleWGS_300_E20_F05"
[[1]]
NULL

[[2]]
NULL

[[3]]
NULL

[[4]]
NULL

[[5]]
NULL

[[6]]
NULL

[[7]]
NULL

[[8]]
NULL

[[9]]
NULL

[[10]]
NULL

[[11]]
NULL

[[12]]
NULL

[[13]]
NULL

[[14]]
NULL

[[15]]
NULL

[[16]]
NULL

[[17]]
NULL

[[18]]
NULL

[[19]]
NULL

[[20]]
NULL

[[21]]
NULL

[[22]]
NULL

[[23]]
NULL

[[24]]
NULL

[[25]]
NULL

[[26]]
NULL

[[27]]
NULL

[[28]]
NULL

[[29]]
NULL

[[30]]
NULL

[[31]]
NULL

[[32]]
NULL

[[33]]
NULL

[[34]]
NULL

[[35]]
NULL
       

Count all samples together and circos it.

save.image(file = "/home/botos/SVRAW1/botos/2023_02_08_NUMTS/final_numts/R/numts_R_process.RData",compress = "gzip")
LS0tCnRpdGxlOiAiTlVNVFMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCgoKIyMjQmVmb3JlIG9jbnRpbnVpbmcgc2hhbGwgY2hlY2sgdG8gYWRkIHRoZSBpbnQoQ0hSKSBmcm9tIHRoZSBweXRob24gc2NyaXB0Li4uLiBhbmQgcmVydW4gYWxsIHRoZSBzYW1wbGVzLgoKCiMjI0xpYnJhcmllcwpgYGB7cn0KLmxpYlBhdGhzKCIvZGF0YS9ib3Rvcy9STGlicy8iKQojaW5zdGFsbC5wYWNrYWdlcygid2VzYW5kZXJzb24iKQpsaWJyYXJ5KHdlc2FuZGVyc29uKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKbGlicmFyeShicmV3KQpsaWJyYXJ5KGNpcmNsaXplKQpsaWJyYXJ5KEdlbm9taWNSYW5nZXMpCmxpYnJhcnkoSVJhbmdlcykKbGlicmFyeShrYXJ5b3Bsb3RlUikKCmBgYAoKCiMjIyBSZWFkIGZpbGVzIApgYGB7cn0KIyNMb2FkIHRoZSBkYXRhCmZpbGVzIDwtIGxpc3QuZmlsZXMoYWxsLmZpbGVzID0gVFJVRSxwYXRoID0gIi9kYXRhL2JvdG9zLzIwMjJfMTJfMDFfTlVNVFNfQWVkZXNfQWVneXB0aS8iLAogICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiKi5tdC5kaXNjLnNhbS5jbHVzdGVyLnN1bW1hcnkudHN2IiwKICAgICAgICAgICAgICAgICAgICByZWN1cnNpdmUgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICBmdWxsLm5hbWVzID0gVFJVRSkKI1NvcnQgdGhlIGZpbGVzIGJ5IHRoZSBudW1iZXIgb2Ygb3V0cHV0CmZpbGVzIDwtIGZpbGVzW29yZGVyKG5jaGFyKGZpbGVzKSldCmZpbGVzCmBgYAoKCgpgYGB7cn0KI2ZpbGVzCiNuYW1lX2ZpbGVzIDwtIGdzdWIoIi9ob21lL21hcml1cy9Eb2N1bWVudHMvUHJvamVjdHMvcHJzYS8wMl9EYXRhL1NUQVIvbWFwcGluZy9yZWxlYXNlMTAyLyIsIiIsZmlsZXMpCiMgbmFtZV9maWxlcyA8LSBnc3ViKCJEOi9QaEQvUHJvamVjdHMvcHJzYS8wMl9EYXRhL1NUQVIvbWFwcGluZy9yZWxlYXNlMTAyLyIsIiIsZmlsZXMpCm5hbWVfZmlsZXMgPC0gZ3N1YigiL2RhdGEvYm90b3MvMjAyMl8xMl8wMV9OVU1UU19BZWRlc19BZWd5cHRpLy9OVU1UU19PVVRQVVRfIiwiIiwKICAgICAgICAgICAgICAgICAgIGdzdWIoIi5tdC5kaXNjLnNhbS5jbHVzdGVyLnN1bW1hcnkudHN2IiwiIiwKICAgICAgICAgICAgICAgICAgICAgICBnc3ViKCJXR1MuKkZbMC05XVswLTldKi8iLCIiLGZpbGVzKSkpCgpuYW1lcyhmaWxlcykgPC0gbmFtZV9maWxlcwojaGVhZChmaWxlcykKI1JlYWQgaXQgaW5zaWRlIGxpc3RzLgojbGFwcGx5KG5hbWVzKGZpbGVzKSxmdW5jdGlvbih4KSBoZWFkKHgpKQpkZnNfbnVtdHMgPC0gbGFwcGx5KGZpbGVzLGZ1bmN0aW9uKGZqKSByZWFkLnRhYmxlKGZqLGhlYWRlciA9IEZBTFNFKSkKcGFzdGUwKCJMaXN0IG9mICIsbGVuZ3RoKGRmc19udW10cyksIiBzYW1wbGVzLlxuIikKCgojIFNwbGl0IHRoZSBjb2x1bW4gaW50byB0aGUgcG9zaXRpb24gZGF0YQpkZnNfbnVtdHNfcG9zIDwtIGxhcHBseShkZnNfbnVtdHMsZnVuY3Rpb24oZGYpIHsKICBzZXBhcmF0ZShkYXRhID0gZGYsY29sID0gVjMsaW50byA9IGMoImNociIsInN0YXJ0IiwiZW5kIiwiTVQiLCJtdF9zdGFydCIsIm10X2VuZCIpLHNlcCA9ICJfIikKfSkKCiMgYWRkIHRoZSBsZW5ndGggb2YgdGhlIHNlZ21lbnQgaW4gdGhlIGNociBvciBtdCBjaHJvbW9zb21lcwpkZnNfbnVtdHNfcG9zX21hdGNoX2xlbiA8LSBsYXBwbHkoZGZzX251bXRzX3BvcyxmdW5jdGlvbihkZikgewogIGRmIDwtIGRwbHlyOjptdXRhdGUoZGYsCiAgICAgICAgICAgICAgICAgICAgICBjaHJfbWF0Y2hMZW4gPSBhcy5pbnRlZ2VyKGVuZCkgLSBhcy5pbnRlZ2VyKHN0YXJ0KSwKICAgICAgICAgICAgICAgICAgICAgIG10X21hdGNoTGVuID0gYXMuaW50ZWdlcihtdF9lbmQpIC0gYXMuaW50ZWdlcihtdF9zdGFydCkpCiAgcmV0dXJuKGRmKX0pCgojcHJpbnQKCmRmc19udW10c19wb3NfbWF0Y2hfbGVuJFdHU18wMTdfRTIwX0YwMwpgYGAKCgojIyMgQ2hlY2sgbmFtZXMKYGBge3J9CgojIFY1ID0gQ2x1c3RlciBzZXF1ZW5jZXMgdGhhdCBhcmUgaW4gdGhlIHNhbWUgY2x1c3RlciA1MDBicCBhcGFydCBnYXAuCiMgVjYgPSBjbHVzdGVyIG9mIHJlYWQgc2VxdWVuY2VzIHRoYXQgYXJlIG1heCA1MDBicCBhcGFydCBhbmQgbWluaW51bSAyCmxhcHBseShkZnNfbnVtdHNfcG9zX21hdGNoX2xlbixmdW5jdGlvbihkZikgewogIGRmW1siVjIiXV1bMV0gCiAgIyBuYW1lcyhkZikKICAjIGRmICU+JSBkcGx5cjo6ZmlsdGVyKGNociAlaW4lIGMoMSwyLDMpKSAlPiUgZHBseXI6OmZpbHRlcihjaHJfbWF0Y2hMZW4gPiA1ICYgbXRfbWF0Y2hMZW4gPiA1KSAlPiUgIGRwbHlyOjphcnJhbmdlKFY2KQogIH0pCgpgYGAKCgoKCiMjI1Zpc3VhbGl6ZSB0aGUgZGF0YSBpbiB2aW9saW5zCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCiMgSXRlcmF0ZSBvdmVyIHRoZSBsaXN0IG9mIGRhdGFmcmFtZXMKcGxvdHNfZGZfbnVtdHMgPC0gbGFwcGx5KGRmc19udW10c19wb3NfbWF0Y2hfbGVuLGZ1bmN0aW9uKGRmKXsKICAjIENyZWF0ZSB0aGUgcGxvdAogIGZpZyA8LSBnZ3Bsb3QoZGYgICU+JSBkcGx5cjo6Z3JvdXBfYnkoVjIpICU+JSBkcGx5cjo6ZmlsdGVyKGNocl9tYXRjaExlbiA+IDUgJiBtdF9tYXRjaExlbiA+IDUpLCBhZXMoeD1jaHJfbWF0Y2hMZW4seT0iIikpICsKICAgIGdlb21fdmlvbGluKGZpbGw9IiNGQUYwRTYiLCBhbHBoYT0wLjQpICsKICAgIGdlb21faml0dGVyKGFlcyhjb2xvcj0iTnVjbGVhciIpLCBzaXplPTMsIGFscGhhPTAuMyxzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgICAjZ2VvbV9ib3hwbG90KHdpZHRoPTAuMSkgKwogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz0iIzAwMDA4MCIpICsKICAgICMgeGxpbSgtMzAsbWF4KGRmJGNocl9tYXRjaExlbikrMzApICsKICAgICN4bGltKDAsMTEwMCkgKwogICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDExMDAsMTAwKSxsaW1pdHM9YygtMzAsMTEwMCkpICsKICAgIGxhYnModGl0bGU9cGFzdGUwKCJOdWNsZWFyOiAiLHVuaXF1ZShkZiRWMikpKSArCiAgICB0aGVtZShheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiKSwKICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIpLAogICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0PTEpKQogIAogIGZpZzIgPC0gZ2dwbG90KCBkZiAlPiUgZHBseXI6Omdyb3VwX2J5KFYyKSAlPiUgZHBseXI6OmZpbHRlcihjaHJfbWF0Y2hMZW4gPiAwICYgbXRfbWF0Y2hMZW4gPiAwKSwgYWVzKHg9bXRfbWF0Y2hMZW4seT0iIikpICsKICAgIGdlb21fdmlvbGluKGZpbGw9IiNGQUYwRTYiLCBhbHBoYT0wLjQpICsKICAgIGdlb21faml0dGVyKGFlcyhjb2xvcj0iTWl0b2Nob25kcmlhbCIpLCBzaXplPTMsIGFscGhhPTAuMyxzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgICAjZ2VvbV9ib3hwbG90KHdpZHRoPTAuMSkgKwogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz0iIzgwMDAyMCIpICsKICAgICMgeGxpbSgtMzAsbWF4KGRmJG10X21hdGNoTGVuKSszMCkgKwogICAgI3hsaW0oMCwxMjkwMCkgKwogICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDEyOTAwLDUwMCksbGltaXRzPWMoLTMwLDEyOTAwKSkgKwogICAgbGFicyh0aXRsZT1wYXN0ZTAoIk1pdG9jaG9uZHJpYWw6ICIsdW5pcXVlKGRmJFYyKSkpICsKICAgIHRoZW1lKGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGlja3MueT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIpLAogICAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiksCiAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSkpCiAgCiAgIyBQcmludCB0aGUgcGxvdAogIHByaW50KGxpc3QoZmlnLGZpZzIpKQogIAogICMgQWRkIHRoZSBwbG90IHRvIHRoZSBsaXN0CiAgI3Bsb3RzIDwtIGMocGxvdHMsIGxpc3QoZmlnKSkKICByZXR1cm4ocGxvdHM9bGlzdChmaWcsZmlnMikpCn0pCgpgYGAKCgoKYGBge3IsZmlnLndpZHRoPTgsZmlnLmhlaWdodD04fQoKcGFyKG1mcm93ID0gYygzNSwgMSkpIywgbWFyID0gcmVwKDAuNSwgNCkpCmxpYnJhcnkoZ3JpZEV4dHJhKQpsYXBwbHkobmFtZXMocGxvdHNfZGZfbnVtdHMpLGZ1bmN0aW9uKG5tKSB7CiAgZ3JpZC5hcnJhbmdlKGdyb2JzPXBsb3RzX2RmX251bXRzW1tubV1dLG5jb2w9Mil9KQogIApgYGAKCgoKIyMjIEZpbHRlciBudW10cyB0aGF0IGFyZSBub3QgMCBpbiB0aGUgTVQgb3IgdGhlIENIUiBhbmQgc2hvdyBob3cgbWFueSBudW10cyBwZXIgUklMLiAoaW5sY3VkZSBtYXliZSB0aGUgY2x1c3RlcmluZyBvZiB0aGUgbnVtdHMgbGF0ZXIpCmBgYHtyfQpsYXBwbHkoZGZzX251bXRzX3Bvc19tYXRjaF9sZW4sZnVuY3Rpb24oZGYpIHsKICBkZiAlPiUgZHBseXI6Omdyb3VwX2J5KFYyKSAlPiUgZHBseXI6OmZpbHRlcihjaHIgJWluJSBjKDEsMiwzKSkgJT4lIGRwbHlyOjpmaWx0ZXIoY2hyX21hdGNoTGVuID4gMjAgJiBtdF9tYXRjaExlbiA+IDIwKSAlPiUgZHBseXI6OnN1bW1hcmlzZShuPW4oKSl9KQpgYGAKCgoKIyMjIyBMaXN0IG9mIFNhbXBsZXMgYW5kIG51bWJlciBvZiBudW10cyBwZXIgc2FtcGxlIGluIHRoZSBDaHIgMSwyLDMKYGBge3IsZmlnLndpZHRoPTE5LGZpZy5oZWlnaHQ9MTJ9CiMgY291bnRzX29mX251bXRzX2xvbmdlcl90aGFuXzIwYnAgPC0gbGFwcGx5KGRmc19udW10c19wb3NfbWF0Y2hfbGVuLGZ1bmN0aW9uKGRmKSB7CiMgICBkZiAlPiUgZHBseXI6Omdyb3VwX2J5KFYyKSAlPiUgZHBseXI6OmZpbHRlcihjaHIgJWluJSBjKDEsMiwzKSkgJT4lIGRwbHlyOjpmaWx0ZXIoY2hyX21hdGNoTGVuID4gMjAgJiBtdF9tYXRjaExlbiA+IDIwKSAlPiUgZHBseXI6OnN1bW1hcmlzZShuPW4oKSl9KQojIAoKY291bnRzX29mX251bXRzX2xvbmdlcl90aGFuXzIwYnAgPC0gbGFwcGx5KGRmc19udW10c19wb3NfbWF0Y2hfbGVuLGZ1bmN0aW9uKGRmKSBkZiAlPiUgZHBseXI6OmZpbHRlcihjaHIgJWluJSBjKDEsMiwzKSkgJT4lIGRwbHlyOjpmaWx0ZXIoY2hyX21hdGNoTGVuID4gMjAgJiBtdF9tYXRjaExlbiA+IDIwKSAgICU+JSBkcGx5cjo6bXV0YXRlX2F0KGMoIm10X3N0YXJ0IiwibXRfZW5kIiwibXRfbWF0Y2hMZW4iKSxhcy5udW1lcmljKSAlPiUgZ3JvdXBfYnkoZ3JvdXAgPSBjdXQobXRfbWF0Y2hMZW4sIGJyZWFrcyA9IHNlcSgwLDE3MDAwLDUwKSkpICU+JSBzdW1tYXJpemUobXRfbWF0Y2hMZW4gPSBuKCksc2FtcGxlSUQgPSBkZltbMl1dWzFdKSkKCmNvdW50c19vZl9udW10c19sb25nZXJfdGhhbl8yMGJwX2RmIDwtIGRvLmNhbGwocmJpbmQsY291bnRzX29mX251bXRzX2xvbmdlcl90aGFuXzIwYnApCgojZGlyLmNyZWF0ZSgiL2hvbWUvYm90b3MvU1ZSQVcxL2JvdG9zLzIwMjNfMDJfMDhfTlVNVFMvZmluYWxfbnVtdHMvVGFibGUiLHJlY3Vyc2l2ZSA9IFRSVUUpCgp3cml0ZS50YWJsZShjb3VudHNfb2ZfbnVtdHNfbG9uZ2VyX3RoYW5fMjBicF9kZixmaWxlID0gIi9ob21lL2JvdG9zL1NWUkFXMS9ib3Rvcy8yMDIzXzAyXzA4X05VTVRTL2ZpbmFsX251bXRzL1RhYmxlL251bXRzX3Jhbmdlc19hbGxfc2FtcGxlcy5jc3YiLHNlcCA9ICIsIikKYGBgCgoKYGBge3IsZmlnLndpZHRoPTI2LGZpZy5oZWlnaHQ9Mjl9CnAgPC0gY291bnRzX29mX251bXRzX2xvbmdlcl90aGFuXzIwYnBfZGYgJT4lIGdncGxvdChhZXMoeD1hcy5mYWN0b3IoZ3JvdXApLCB5PW10X21hdGNoTGVuLGZpbGwgPSAoInJlZCIpKSkgKwogIGdlb21fY29sKGFscGhhPTAuNykgKwogICNnZW9tX2NvbChkYXRhPSBkYXRhVFsxOjM5LF0sbWFwcGluZyA9IGFlcyh4PWRhdGUseT1pbmNvbWUvMiAsZmlsbD1kMSkpICsKICBnZW9tX2xpbmUoZGF0YT0gY291bnRzX29mX251bXRzX2xvbmdlcl90aGFuXzIwYnBfZGYsZ3JvdXA9MSxtYXBwaW5nPWFlcyh4PWFzLmZhY3Rvcihncm91cCkseT1tdF9tYXRjaExlbikpICsKICAjIGdlb21fcG9pbnQoZGF0YSA9IGNvdW50c19vZl9udW10c19sb25nZXJfdGhhbl8yMGJwX2RmLAogICMgICAgICAgICAgICBhZXMoeCA9IGNvdW50c19vZl9udW10c19sb25nZXJfdGhhbl8yMGJwX2RmJGdyb3VwW3doaWNoLm1heChjb3VudHNfb2ZfbnVtdHNfbG9uZ2VyX3RoYW5fMjBicF9kZiRtdF9tYXRjaExlbildLAogICMgICAgICAgICAgICAgICAgeSA9IGNvdW50c19vZl9udW10c19sb25nZXJfdGhhbl8yMGJwX2RmJG10X21hdGNoTGVuW3doaWNoLm1heChjb3VudHNfb2ZfbnVtdHNfbG9uZ2VyX3RoYW5fMjBicF9kZiRtdF9tYXRjaExlbildKSwgY29sb3I9ImJsYWNrIixzaXplPTMpICsKICAjZ2VvbV9hcmVhKHBvc2l0aW9uID0gImlkZW50aXR5IiwgYWxwaGEgPSAwLjUsY29sb3I9InJlZCIpICsKICAjZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICAjc3RhdF9kZW5zaXR5KGFlcyhnZW9tPSJsaW5lIixwb3NpdGlvbj0iaWRlbnRpdHkiKSkgKyAKICAjZ2VvbV9kZW5zaXR5KGFlcyhhZnRlcl9zdGF0KGNvdW50KSkpICsKICAjeGxpbShjKDAsMTcwMDApKSArCiAgI2Nvb3JkX2ZsaXAoKSArCiAgbGFicyhmaWxsID0gIk51bXRzIExlbmd0aCBHcm91cCIpICsKICBzY2FsZV94X2Rpc2NyZXRlKCJncm91cCIpICsKICBmYWNldF93cmFwKH5zYW1wbGVJRCxuY29sID0gMikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSkpIAoKcAoKc3ZnKGZpbGVuYW1lID0gIi9ob21lL2JvdG9zL1NWUkFXMS9ib3Rvcy8yMDIzXzAyXzA4X05VTVRTL2ZpbmFsX251bXRzL1Bsb3RzL251bXRzX3Jhbmdlc19hbGxfc2FtcGxlc19iYXJwbG90c19wZXJfc2FtcGxlLnN2ZyIsCiAgICB3aWR0aCA9IDE2LAogICAgaGVpZ2h0ID0gMzEpCnAKZGV2Lm9mZigpCmBgYAoKCgojIyMjIEdlbmVzIGZvciBjaXJjb3MgCgpgYGB7cn0KIyMjYWRkIG10IGdlbmVzCm10X2dlbmVzX2FlIDwtIHJlYWQudGFibGUoZmlsZSA9ICIvaG9tZS9ib3Rvcy9TVlJBVzEvYm90b3MvMjAyM18wMl8wOF9OVU1UUy9WaXN1YWxpemF0aW9uX3NhbXBsZXMvbXRfYWVfZ3RmX2dlbmVzX3RybmFfcnJuYS50eHQiLHNlcCA9ICJcdCIpCiAKIyB1bmlxdWUobXRfZ2VuZXNfYWUkVjUpIAojIHVuaXF1ZShtdF9nZW5lc19hZSRWNikgCiMgdW5pcXVlKG10X2dlbmVzX2FlJFY3KQojIHVuaXF1ZShtdF9nZW5lc19hZSRWNCkgCgptdF9nZW5lc19hZSRwYXN0ZSA8LSBwYXN0ZShtdF9nZW5lc19hZSRWNSxtdF9nZW5lc19hZSRWNixzZXA9Il8iKQptdF9nZW5lc19hZSA8LSBtdF9nZW5lc19hZVssYygiVjIiLCJWMyIsInBhc3RlIildCm10X2dlbmVzX2FlIDwtIG10X2dlbmVzX2FlICU+JSBkcGx5cjo6ZmlsdGVyKHBhc3RlICE9ICJfIikgJT4lIGRwbHlyOjptdXRhdGUoR2VuZXM9IHN0cl9yZW1vdmUocGFzdGUsIl5ffF8kIikpCm10X2dlbmVzX2FlIDwtIG10X2dlbmVzX2FlWyxjKCJWMiIsIlYzIiwiR2VuZXMiKV0KbXRfZ2VuZXNfYWUkY2hyIDwtICJjaHJNIgptdF9nZW5lc19hZSR2YWx1ZSA8LSAxCm10X2dlbmVzX2FlIDwtIG10X2dlbmVzX2FlWyxjKCJjaHIiLCJWMiIsIlYzIiwidmFsdWUiLCJHZW5lcyIpXQpjb2xuYW1lcyhtdF9nZW5lc19hZSkgPC0gYygiY2hyIiwic3RhcnQiLCJlbmQiLCJ2YWx1ZSIsImdlbmUiKQptdF9nZW5lc19hZSRzdGFydCA8LSBtdF9nZW5lc19hZSRzdGFydCAqIDEwMDAwMAptdF9nZW5lc19hZSRlbmQgPC0gbXRfZ2VuZXNfYWUkZW5kICogMTAwMDAwCm10X2dlbmVzX2FlIDwtIG10X2dlbmVzX2FlICU+JSBkcGx5cjo6bXV0YXRlX2F0KGMoInN0YXJ0IiwiZW5kIiwidmFsdWUiKSxhcy5udW1lcmljKQoKIyBjaHJfZ2VuZXNfYWUgPC0gZGYxX2xpbmtfV0dTXzAxN19FMjBfRjAzCiMgY2hyX2dlbmVzX2FlJGdlbmUgPC0gIkVjeGFtcGxlLjIuMWFhLjIiCgojIGFubm9fZ2VuZXNfYWUgPC0gcmJpbmQobXRfZ2VuZXNfYWUsY2hyX2dlbmVzX2FlKQojIAojIGFubm9fZ2VuZXNfYWUgPC0gYW5ub19nZW5lc19hZSAlPiUgZHBseXI6Om11dGF0ZV9hdChjKCJzdGFydCIsImVuZCIsInZhbHVlIiksYXMubnVtZXJpYykKCmBgYAoKYGBge3J9CgojICMgcnVuIGFuZCBjb21tZW5udCBhbmQgcmUgcnVubiB0aGUgb25lIG9uIHRvcAojIG10X2dlbmVzX2FlIDwtIHJlYWQudGFibGUoZmlsZSA9ICIvaG9tZS9ib3Rvcy9TVlJBVzEvYm90b3MvMjAyM18wMl8wOF9OVU1UUy9WaXN1YWxpemF0aW9uX3NhbXBsZXMvbXRfYWVfZ3RmX2dlbmVzX3RybmFfcnJuYS50eHQiLHNlcCA9ICJcdCIpCiMgbXRfZ2VuZXNfMiA8LSBtdF9nZW5lc19hZSAlPiUgZHBseXI6OmZpbHRlcihWMSA9PSAiZ2VuZSIpICU+JSBkcGx5cjo6c2VsZWN0KFYyLFYzLFY2KSAlPiUgZHBseXI6OmZpbHRlcihWNiAhPSAiIikgJT4lIGRwbHlyOjptdXRhdGUoY2hyPSJjaHJNIiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IDEpCiMgbXRfZ2VuZXNfMiA8LSBtdF9nZW5lc18yWyxjKCJjaHIiLCJWMiIsIlYzIiwidmFsdWUiLCJWNiIpXQojIGNvbG5hbWVzKG10X2dlbmVzXzIpIDwtIGMoImNociIsInN0YXJ0IiwiZW5kIiwidmFsdWUiLCJnZW5lIikKIyBtdF9nZW5lc18yJHN0YXJ0IDwtIG10X2dlbmVzXzIkc3RhcnQgKiAxMDAwMDAKIyBtdF9nZW5lc18yJGVuZCA8LSBtdF9nZW5lc18yJGVuZCAqIDEwMDAwMAojIG10X2dlbmVzXzIgPC0gbXRfZ2VuZXNfMiAlPiUgZHBseXI6Om11dGF0ZV9hdChjKCJzdGFydCIsImVuZCIsInZhbHVlIiksYXMubnVtZXJpYykKCmBgYAoKCiMjIyBBcHBseSBjaXJjb3MgZm9yIGFsbCBzYW1wbGVzIApgYGB7cixmaWcuaGVpZ2h0PTEwLGZpZy53aWR0aD0xMH0KY2lyY29zX1JJTF9wbG90cyA8LSBsYXBwbHkoZGZzX251bXRzX3Bvc19tYXRjaF9sZW4sZnVuY3Rpb24oZGYpIHsKICAKICAjcG5nKGZpbGVuYW1lID0gcGFzdGUwKCIvaG9tZS9ib3Rvcy9TVlJBVzEvYm90b3MvMjAyM18wMl8wOF9OVU1UUy9maW5hbF9udW10cy9QbG90cy8iLGRmW1siVjIiXV1bMV0sIl9jaXJjb3NfY2hyX3RvX210LnBuZyIpLHdpZHRoID0gNjgwLGhlaWdodCA9IDY4MCkKICAjc3ZnKGZpbGVuYW1lID0gcGFzdGUwKCIvaG9tZS9ib3Rvcy9TVlJBVzEvYm90b3MvMjAyM18wMl8wOF9OVU1UUy9maW5hbF9udW10cy9QbG90cy8iLGRmW1siVjIiXV1bMV0sIl9jaXJjb3NfY2hyX3RvX210LnN2ZyIpLHdpZHRoID0gMTAsaGVpZ2h0ID0gMTApCgogIAogICNydW4gY29kZSBmb3IgY2lyY29zCiAgZGZfcyA8LSBkZiAlPiUgZHBseXI6Omdyb3VwX2J5KGNocikgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKGNocl9tYXRjaExlbiA+IDIwICYgbXRfbWF0Y2hMZW4gPiAyMCkgJT4lCiAgICBkcGx5cjo6YXJyYW5nZShWNikgJT4lIAogICAgZHBseXI6OnNlbGVjdChjaHIsc3RhcnQsZW5kLGNocl9tYXRjaExlbixtdF9zdGFydCxtdF9lbmQsbXRfbWF0Y2hMZW4pICU+JQogICAgZHBseXI6OmRpc3RpbmN0KCkKICAKICBkZl9zJG10X3N0YXJ0IDwtIGFzLmludGVnZXIoZGZfcyRtdF9zdGFydCkqMTAwMDAwCiAgZGZfcyRtdF9lbmQgPC0gYXMuaW50ZWdlcihkZl9zJG10X2VuZCkqMTAwMDAwCiAgCiAgY2hyX2RmX3MgPC0gZGZfcyAlPiUgZHBseXI6OmZpbHRlcihjaHIgJWluJSBjKDEsMiwzKSkgJT4lIGRwbHlyOjpzZWxlY3QoY2hyLHN0YXJ0LGVuZCxjaHJfbWF0Y2hMZW4pICU+JSBkcGx5cjo6bXV0YXRlKGNocj1wYXN0ZTAoImNociIsY2hyKSkKICBjb2xuYW1lcyhjaHJfZGZfcykgPC0gYygiY2hyIiwic3RhcnQiLCJlbmQiLCJ2YWx1ZSIpCiAgbXRfZGZfcyA8LSBkZl9zICU+JSBkcGx5cjo6ZmlsdGVyKGNociAlaW4lIGMoMSwyLDMpKSAlPiUgZHBseXI6OnNlbGVjdChtdF9zdGFydCxtdF9lbmQsbXRfbWF0Y2hMZW4pCiAgbXRfZGZfcyRjaHIgPC0gImNock0iCiAgY29sbmFtZXMobXRfZGZfcykgPC0gYygiY2hyIiwic3RhcnQiLCJlbmQiLCJ2YWx1ZSIpCgogIGNocl9kZl9zJHN0YXJ0IDwtIGFzLmludGVnZXIoY2hyX2RmX3Mkc3RhcnQpCiAgY2hyX2RmX3MkZW5kIDwtIGFzLmludGVnZXIoY2hyX2RmX3MkZW5kKQogIGNocl9tdF9kZl9zIDwtIGRwbHlyOjpiaW5kX3Jvd3MoY2hyX2RmX3MsbXRfZGZfcykKICAKICAjQ3JlYXRlIHRoZSBjaHIgYW5kIG10IHJlZ2lvbnMgb2YgdGhlIG51bXRzIGJ5IHNwbGl0dGluZyB0aGVtLgoKICBkZjFfbGluayA8LSBjaHJfbXRfZGZfcyAlPiUgZHBseXI6OmZpbHRlcihjaHIgJWluJSBjKCJjaHIxIiwiY2hyMiIsImNocjMiKSkKICBkZjJfbGluayA8LSBjaHJfbXRfZGZfcyAlPiUgZHBseXI6OmZpbHRlcihjaHIgJWluJSBjKCJjaHJNIikpIAogIAogIAogIAogICMgUGxvdCB0aGUgY2lyY29zCiAgI2NpcmNvcy5wYXIoInRyYWNrLmhlaWdodCI9MC44LCBnYXAuZGVncmVlPTUsIGNlbGwucGFkZGluZz1jKDAsIDAsIDAsIDApKQogIGNpcmNvcy5jbGVhcigpCiAgY2lyY29zLnBhcihnYXAuZGVncmVlPTUpCgogIHJlZl9mZF9hZSA8LSBkYXRhLmZyYW1lKCJDaHJvbW9zb21lIj1jKCJjaHIxIiwiY2hyMiIsImNocjMiLCJjaHJNIiksIkNocm9tU3RhcnQiPWMoMCwwLDAsMCksIkNocm9tZW5kIj1jKDMxMDgyNzAyMiw0NzQ0MjU3MTYsNDA5Nzc3NjcwLDE2NzkwKjEwMDAwMCkpCgogICNjaXJjb3MuZ2Vub21pY0luaXRpYWxpemUocmVmX2ZkX2FlKQogIGNpcmNvcy5nZW5vbWljSW5pdGlhbGl6ZShyZWZfZmRfYWUscGxvdFR5cGUgPSBOVUxMKQogIGNpcmNvcy5nZW5vbWljTGFiZWxzKG10X2dlbmVzX2FlICxsYWJlbHMuY29sdW1uID0gNSwgY2V4PTAuNyxsaW5lX2x3ZD0wLjYsIGxpbmVfY29sPSJncmV5MjAiLCBjb25uZWN0aW9uX2hlaWdodCA9IDAuMDE5LAogICAgICAgICAgICAgICAgICAgICAgIGxhYmVsc19oZWlnaHQgPSAwLjIsbmljZUZhY2luZyA9IFRSVUUsc2lkZSA9ICJvdXRzaWRlIikKICAjIGNpcmNvcy5nZW5vbWljTGFiZWxzKG10X2dlbmVzXzIgLGxhYmVscy5jb2x1bW4gPSA1LCBjZXg9MC41LGxpbmVfbHdkPTAuNiwgbGluZV9jb2w9ImdyZXkyMCIsIGNvbm5lY3Rpb25faGVpZ2h0ID0gMC4wNSwgbGFiZWxzX2hlaWdodCA9IDAuMixuaWNlRmFjaW5nID0gVFJVRSxzaWRlID0gIm91dHNpZGUiKQoKICBjaXJjb3MudHJhY2soeWxpbT1jKDAsIDEpLCBwYW5lbC5mdW49ZnVuY3Rpb24oeCwgeSkgewogICAgY2hyPUNFTExfTUVUQSRzZWN0b3IuaW5kZXgKICAgIHhsaW09Q0VMTF9NRVRBJHhsaW0KICAgIHlsaW09Q0VMTF9NRVRBJHlsaW0KICAgIGNpcmNvcy50ZXh0KG1lYW4oeGxpbSksIG1lYW4oeWxpbSksIGNociwgY2V4PTAuOCl9LCBiZy5jb2wgPSBjKCIjMDAwMEZGNDAiLCIjMDAwMEZGNDAiLCIjMDAwMEZGNDAiLCIjRkYwMDAwNDAiKSwgYmcuYm9yZGVyPUYsIHRyYWNrLmhlaWdodD0wLjA2KQogIAogIGNpcmNvcy50cmFjayh0cmFjay5pbmRleCA9IGdldC5jdXJyZW50LnRyYWNrLmluZGV4KCksCiAgICAgICAgICAgICAgIHBhbmVsLmZ1biA9IGZ1bmN0aW9uKHgsIHkpIHsKICAgICAgICAgICAgICAgICBjaXJjb3MuZ2Vub21pY0F4aXMoaCA9ICJib3R0b20iLCBkaXJlY3Rpb24gPSAiaW5zaWRlIixsYWJlbHMuY2V4ID0gMC42LHRpY2tMYWJlbHNTdGFydEZyb21aZXJvID0gVFJVRSl9KQogIAogIHNldF90cmFja19nYXAoZ2FwID0gMC4wNCkKICAKICAjIGNpcmNvcy5nZW5vbWljVHJhY2soY2hyX210X2RmX3MgJT4lIGRwbHlyOjpkaXN0aW5jdCgpLAogICMgICAgICAgICAgICAgICAgICAgICB0cmFjay5oZWlnaHQ9MC4xLAogICMgICAgICAgICAgICAgICAgICAgICBwYW5lbC5mdW4gPSBmdW5jdGlvbihyZWdpb24sIHZhbHVlLCAuLi4pIHsKICAjICAgICAgICAgICAgICAgICAgICAgICBjaXJjb3MuZ2Vub21pY1BvaW50cyhyZWdpb24sIHZhbHVlLAogICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBjaCA9IDYsCiAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2V4ID0gMS42LAogICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbD0iYmxhY2siKX0pI2NvbD1pZmVsc2UodmFsdWVbWzFdXSA+IDE1MCwicmVkIiwiYmxhY2siKSl9KQogIGNpcmNvcy5nZW5vbWljVHJhY2soY2hyX210X2RmX3MgJT4lIGRwbHlyOjpkaXN0aW5jdCgpLAogICAgICAgICAgICAgICAgICAgICAgdHJhY2suaGVpZ2h0PTAuMiwKICAgICAgICAgICAgICAgICAgICAgIHBhbmVsLmZ1biA9IGZ1bmN0aW9uKHJlZ2lvbix2YWx1ZSwuLi4pIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2lyY29zLmdlbm9taWNSZWN0KHJlZ2lvbiwgdmFsdWUsY29sID0gIiNGRjAwMDA0MCIsLi4uKX0pCiAgICAgICAgICAgICAgICAgICAgICAgICNjaXJjb3MuZ2Vub21pY1BvaW50cyhyZWdpb24sIHZhbHVlLHBjaCA9IDYsY2V4ID0gMS42LGNvbD0iYmxhY2siKX0pI2NvbD1pZmVsc2UodmFsdWVbWzFdXSA+IDE1MCwicmVkIiwiYmxhY2siKSl9KQogIAoKICAKICAjY2lyY29zLnVwZGF0ZShzZWN0b3IuaW5kZXggPSAiY2hyTSIsdHJhY2suaW5kZXggPSA0KQogICNjaXJjb3MucG9pbnRzKHg9Y29sPSJyZWQiKQogIAogIGNvbCA8LSBhbHBoYSh3ZXNfcGFsZXR0ZSgiWmlzc291MSIsIG4gPSBucm93KGRmMl9saW5rKSwgdHlwZSA9ICJjb250aW51b3VzIiksIDAuNCkKICBjaXJjb3MuZ2Vub21pY0xpbmsoZGYxX2xpbmsgJT4lICBkcGx5cjo6bXV0YXRlX2F0KGMoInN0YXJ0IiwiZW5kIiwidmFsdWUiKSxhcy5udW1lcmljKSwKICAgICAgICAgICAgICAgICAgICAgZGYyX2xpbmsgJT4lICBkcGx5cjo6bXV0YXRlX2F0KGMoInN0YXJ0IiwiZW5kIiwidmFsdWUiKSxhcy5udW1lcmljKSwKICAgICAgICAgICAgICAgICAgICAgI3VzZSBsaXJiYXJ5IHdlc2FuZGVyc29uIGh0dHA6Ly93d3cuc3RoZGEuY29tL2VuZ2xpc2gvd2lraS9jb2xvcnMtaW4tcgogICAgICAgICAgICAgICAgICAgICBjb2wgPSBjb2wpCiAgIyBjb2wgPSBjb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwoNSwgIkRhcmsyIikpKG5yb3coZGYyX2xpbmtfV0dTXzAxN19FMjBfRjAzKSkpIyxib3JkZXIgPSBOQSx0cmFuc3BhcmVuY3k9MC4xKQogIHRpdGxlKHBhc3RlMChkZltbIlYyIl1dWzFdKSkKICMgZGV2Lm9mZigpCgp9KQpgYGAKCgojIyMgc2F2ZSB0aGUgdGFibGUgb2YgdGhlIHBsb3RzCmBgYHtyLGZpZy5oZWlnaHQ9OSxmaWcud2lkdGg9OX0KCiN2NSBpcyBjbHVzdGVyIG9mIDUwMGJwIGdhcHMKI3Y2IGlzIGNsdXN0ZXIgb2YgbW9yZSB0aGFuIDIgcmVhZHMgc3VwcG9ydGluZyB0aGUgcHJldmlvdXMgY2x1c3RlcgpsYXBwbHkoZGZzX251bXRzX3Bvc19tYXRjaF9sZW4sZnVuY3Rpb24oZGYpIHsKICBkZl9zIDwtIGRmICU+JSBkcGx5cjo6Z3JvdXBfYnkoY2hyKSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoY2hyX21hdGNoTGVuID4gMjAgJiBtdF9tYXRjaExlbiA+IDIwKSAlPiUKICAgIGRwbHlyOjphcnJhbmdlKFY2KSAlPiUgCiAgICBkcGx5cjo6c2VsZWN0KGNocixzdGFydCxlbmQsY2hyX21hdGNoTGVuLG10X3N0YXJ0LG10X2VuZCxtdF9tYXRjaExlbikgJT4lCiAgICBkcGx5cjo6ZGlzdGluY3QoKSAlPiUgCiAgICB3cml0ZS50YWJsZShwYXN0ZTAoIi9ob21lL2JvdG9zL1NWUkFXMS9ib3Rvcy8yMDIzXzAyXzA4X05VTVRTL2ZpbmFsX251bXRzL1RhYmxlLyIsZGZbWyJWMiJdXVsxXSwiX2Nocl90b19tdF90YWJsZS5jc3YiKSxzZXAgPSAiLCIsY29sLm5hbWVzID0gVFJVRSxyb3cubmFtZXMgPSBGQUxTRSkKfSkKCmBgYAoKCiMjIyBrYXJ5b3R5cGUgcGxvdHRlcgoKYGBge3J9Cm10X2dlbmVzXzJfcmFuZ2VzIDwtIEdSYW5nZXMoc2VxbmFtZXMgPSAiTkNfMDM1MTU5LjEiLHJhbmdlcyA9IElSYW5nZXMoc3RhcnQgPSBtdF9nZW5lc18yJHN0YXJ0LzEwMDAwMCxlbmQgPSBtdF9nZW5lc18yJGVuZC8xMDAwMDApLGdlbmVzPW10X2dlbmVzXzIkZ2VuZSwgeTA9MCx5MT0wLjEzKQojbXRfZ2VuZXNfMl9yYW5nZXMgPC0gR1JhbmdlcyhzZXFuYW1lcyA9IG10X2dlbmVzXzIkY2hyLHJhbmdlcyA9IElSYW5nZXMoc3RhcnQgPSBtdF9nZW5lc18yJHN0YXJ0LzEwMDAwMCxlbmQgPSBtdF9nZW5lc18yJGVuZC8xMDAwMDApLGdlbmVzPW10X2dlbmVzXzIkZ2VuZSwgeTA9MCx5MT0wLjEzKQoKCmBgYAoKCiMjIyMjIyBXcmFuZ2xlIGZvciBlYWNoIHNhbXBsZSB0aGUgZ2Vub21pYyByYW5uZ2VzCgpgYGB7cn0KbGlicmFyeShTNFZlY3RvcnMpCmxpYnJhcnkoR2Vub21pY1JhbmdlcykKbGlicmFyeShJUmFuZ2VzKQpsaWJyYXJ5KGthcnlvcGxvdGVSKQoKbGlzdF9vZl9yZWdpb25zIDwtIGxhcHBseShkZnNfbnVtdHNfcG9zX21hdGNoX2xlbixmdW5jdGlvbihkZil7CiAgCiAgY2F0KHBhc3RlMCgic3RhcnQgd2l0aCBzYW1wbGU6ICIsZGZbWyJWMiJdXVsxXSwiXG4iKSkKICByYW5nZXNfZGYgPC0gR1JhbmdlcyhzZXFuYW1lcyA9IGRmICU+JSBkcGx5cjo6ZmlsdGVyKGNocl9tYXRjaExlbiA+IDIwICYgbXRfbWF0Y2hMZW4gPiAyMCkgJT4lIGRwbHlyOjpmaWx0ZXIoY2hyICVpbiUgYygxLDIsMykpICU+JSBkcGx5cjo6cHVsbChjaHIpLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmdlcyA9SVJhbmdlcyhzdGFydCA9IGFzLm51bWVyaWMoZGYgJT4lIGRwbHlyOjpmaWx0ZXIoY2hyX21hdGNoTGVuID4gMjAgJiBtdF9tYXRjaExlbiA+IDIwKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6OmZpbHRlcihjaHIgJWluJSBjKDEsMiwzKSkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRwbHlyOjpwdWxsKG10X3N0YXJ0KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZCA9IGFzLm51bWVyaWMoZGYgJT4lIGRwbHlyOjpmaWx0ZXIoY2hyX21hdGNoTGVuID4gMjAgJiBtdF9tYXRjaExlbiA+IDIwKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRwbHlyOjpmaWx0ZXIoY2hyICVpbiUgYygxLDIsMykpICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6OnB1bGwobXRfZW5kKSkpLAogICAgICAgICAgICAgICAgICAgICAgIHJlYWxfY2hyPSJjaHJNIikKICAKICByYW5nZXNfZGYgPC0gYXMuZGF0YS5mcmFtZShyYW5nZXNfZGYpCiAgcmFuZ2VzX2RmJHNlcW5hbWVzMiA8LSByYW5nZXNfZGYkc2VxbmFtZXMKICAjU2V0IHRoZSBuYW1lIG9mIHRoZSBjaHJtIHRvIHRoZSBvZmZpY2lhbCBuY2JpIG5hbmUgdGhhdCBpIHVzZSB0byBjcmVhdGUgdW5kZXIgdGhlIGdlbmVzIGZvciBvdmVybGFwcGluZy4KICAjcmFuZ2VzX2RmJHNlcW5hbWVzIDwtICJjaHJNIgogIHJhbmdlc19kZiRzZXFuYW1lcyA8LSAiTkNfMDM1MTU5LjEiCiAgcmFuZ2VzX2RmIDwtIGRwbHlyOjptdXRhdGUocmFuZ2VzX2RmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNocl9zdGFydF9lbmQ9cGFzdGUwKHNlcW5hbWVzLCI6IixzdGFydCwiLSIsZW5kKSkKICAKICBjYXQoImV4dHJhY3RpbmcgcmVnaW9uc1xuIikKICBlbXB0eV9nciA8LSBHUmFuZ2VzKHNlcW5hbWVzID0gY2hhcmFjdGVyKCksIElSYW5nZXMoc3RhcnQgPSBpbnRlZ2VyKCksIGVuZCA9IGludGVnZXIoKSkpCiAgCiAgcmVnczEgPC0gaWYobnJvdyhyYW5nZXNfZGYgJT4lIGRwbHlyOjpmaWx0ZXIoc2VxbmFtZXMyID09IDEpKSAhPSAwKXsKICAgIHRvR1JhbmdlcyhyYW5nZXNfZGYgJT4lIGZpbHRlcihzZXFuYW1lczIgPT0gMSkgJT4lIGRwbHlyOjpwdWxsKGNocl9zdGFydF9lbmQpKQogIH1lbHNlewogIGVtcHR5X2dyfQogIAogIHJlZ3MyIDwtIGlmKG5yb3cocmFuZ2VzX2RmICU+JSBkcGx5cjo6ZmlsdGVyKHNlcW5hbWVzMiA9PSAyKSkgIT0gMCl7CiAgICB0b0dSYW5nZXMocmFuZ2VzX2RmICU+JSBmaWx0ZXIoc2VxbmFtZXMyID09IDIpICU+JSBkcGx5cjo6cHVsbChjaHJfc3RhcnRfZW5kKSkKICB9ZWxzZXsKICBlbXB0eV9ncn0KICAKICByZWdzMyA8LSBpZihucm93KHJhbmdlc19kZiAlPiUgZHBseXI6OmZpbHRlcihzZXFuYW1lczIgPT0gMykpICE9IDApewogICAgdG9HUmFuZ2VzKHJhbmdlc19kZiAlPiUgZmlsdGVyKHNlcW5hbWVzMiA9PSAzKSAlPiUgZHBseXI6OnB1bGwoY2hyX3N0YXJ0X2VuZCkpCiAgfWVsc2V7CiAgZW1wdHlfZ3J9CiAgCiAgcmVnczFfZGYgPC0gYXMuZGF0YS5mcmFtZShyZWdzMSkgJT4lIGRwbHlyOjptdXRhdGUoY2hyb209ImNocjEiKQogIHJlZ3MyX2RmIDwtIGFzLmRhdGEuZnJhbWUocmVnczIpICU+JSBkcGx5cjo6bXV0YXRlKGNocm9tPSJjaHIyIikKICByZWdzM19kZiA8LSBhcy5kYXRhLmZyYW1lKHJlZ3MzKSAlPiUgZHBseXI6Om11dGF0ZShjaHJvbT0iY2hyMyIpCiAgcmVnc19kZiA8LSByYmluZChyZWdzMV9kZixyZWdzMl9kZixyZWdzM19kZikKICBjYXQoImRvbmVcbiIpCiAgcmV0dXJuKHJlZ3NfZGYpfSkKCmBgYAoKYGBge3IsZmlnLndpZHRoPTEyLGZpZy5oZWlnaHQ9NH0KbGlicmFyeShTNFZlY3RvcnMpCgoKCmxhcHBseShuYW1lcyhsaXN0X29mX3JlZ2lvbnMpLGZ1bmN0aW9uKGt0KXsKICAKICAjc3ZnKGZpbGVuYW1lID0gcGFzdGUwKCIvaG9tZS9ib3Rvcy9TVlJBVzEvYm90b3MvMjAyM18wMl8wOF9OVU1UUy9maW5hbF9udW10cy9QbG90cy9rYXJ5dHlwZVBsb3RfIixrdCwibnVtdHNfY2hyLnN2ZyIpLHdpZHRoID0gMTIsaGVpZ2h0ID0gNCkKICAKICBjdXN0b20uZ2Vub21lIDwtIHRvR1JhbmdlcyhkYXRhLmZyYW1lKGNocj1jKCJOQ18wMzUxNTkuMSIpLHN0YXJ0PWMoMCksZW5kPWMoMTY3OTApKSkKICBrcCA8LSBwbG90S2FyeW90eXBlKGdlbm9tZSA9IGN1c3RvbS5nZW5vbWUpCiAga3BEYXRhQmFja2dyb3VuZChrcCwgcjAgPSAwLHIxID0gMC4yNSkKICBrcERhdGFCYWNrZ3JvdW5kKGtwLCByMCA9IDAuMjUscjEgPSAwLjUsY29sPSIjRkYwMDAwNDAiKQogIGtwRGF0YUJhY2tncm91bmQoa3AsIHIwID0gMC41LHIxID0gMC43NSxjb2w9IiNGRjAwMDA0MCIpCiAga3BEYXRhQmFja2dyb3VuZChrcCwgcjAgPSAwLjc1LHIxID0gMSxjb2w9IiNGRjAwMDA0MCIpCiAgCiAgCiAgIAogIAogIAogIGtwUmVjdChrcCxtdF9nZW5lc18yX3Jhbmdlcyxjb2w9InJlZCIpCiAga3BUZXh0KGthcnlvcGxvdCA9IGtwLGRhdGEgPSBtdF9nZW5lc18yX3JhbmdlcyxsYWJlbHMgPSBtdF9nZW5lc18yX3JhbmdlcyRnZW5lcyx5ID0gMC4xNyxjZXg9MC42LGNvbD0icmVkIikKICAKICAjYWRkIG10IHNlcXVlbmNlcyBmcm9tICBlYWNoIGNocm9tb29zb21lCiAgI2FkZCBudW10cyBmcm9tIGNociAxCiAga3BSZWN0KGtwLGRhdGEgPSBsaXN0X29mX3JlZ2lvbnNbW2t0XV0gJT4lIGZpbHRlcihjaHJvbSA9PSAiY2hyMSIpICU+JSB0b0dSYW5nZXMsIHkwID0gMC4zLHkxPTAuNCkgCiAgI2FkZCBudW10cyBmcm9tIGNociAyCiAga3BSZWN0KGtwLGRhdGEgPSBsaXN0X29mX3JlZ2lvbnNbW2t0XV0gJT4lIGZpbHRlcihjaHJvbSA9PSAiY2hyMiIpICU+JSB0b0dSYW5nZXMsIHkwID0gMC42LHkxID0gMC43KQogICNhZGQgbnVtdHMgZnJvbSBjaHIgMwogIGtwUmVjdChrcCxkYXRhID0gbGlzdF9vZl9yZWdpb25zW1trdF1dICU+JSBmaWx0ZXIoY2hyb20gPT0gImNocjMiKSAlPiUgdG9HUmFuZ2VzLCB5MCA9IDAuOCx5MSA9IDAuOSkKICB0aXRsZShwYXN0ZTAoa3QpKQogIAogICNkZXYub2ZmKCkKICAgIAp9KQoKCgpgYGAKCgoKYGBge3IsZmlnLmhlaWdodD0zMixmaWcud2lkdGg9MTJ9CgpsaXN0X29mX3JlZ2lvbnNfSUQgPC0gbGFwcGx5KG5hbWVzKGxpc3Rfb2ZfcmVnaW9ucyksZnVuY3Rpb24obmFtZSkgewogIGRmIDwtIGxpc3Rfb2ZfcmVnaW9uc1tbbmFtZV1dCiAgZGYkSUQgPC0gbmFtZQogIHJldHVybihkZikKfSkKCnN2ZyhmaWxlbmFtZSA9ICIvaG9tZS9ib3Rvcy9TVlJBVzEvYm90b3MvMjAyM18wMl8wOF9OVU1UUy9maW5hbF9udW10cy9QbG90cy9Qb3N0aW9uc19pbl9DSFJfb2ZfbnVtdHMuc3ZnIix3aWR0aCA9IDEwLGhlaWdodCA9IDMyKQpjb21iaW5lZF9saXN0X29mX3JlZ2lvbnNfSUQgPC0gZG8uY2FsbChyYmluZCxsaXN0X29mX3JlZ2lvbnNfSUQpCiMgY29tYmluZWRfbGlzdF9vZl9yZWdpb25zX0lEIDwtIGRwbHlyOjptdXRhdGUoY29tYmluZWRfbGlzdF9vZl9yZWdpb25zX0lELHBvc19jaHJfc3RhcnRfZW5kID0gcGFzdGUwKGNocm9tLCI6IixzdGFydCwiLSIsZW5kKSkKY29tYmluZWRfbGlzdF9vZl9yZWdpb25zX0lEIDwtIGRwbHlyOjptdXRhdGUoY29tYmluZWRfbGlzdF9vZl9yZWdpb25zX0lELHBvc19jaHJfc3RhcnRfZW5kID0gcGFzdGUwKHNlcW5hbWVzLCI6IixzdGFydCwiLSIsZW5kKSkKCnRhYmxlKGNvbWJpbmVkX2xpc3Rfb2ZfcmVnaW9uc19JRCRwb3NfY2hyX3N0YXJ0X2VuZCkgJT4lIHN1YnNldChjb21iaW5lZF9saXN0X29mX3JlZ2lvbnNfSUQkcG9zX2Nocl9zdGFydF9lbmQgPiAxKQoKY29tYmluZWRfbGlzdF9vZl9yZWdpb25zX0lEICU+JSBkcGx5cjo6Z3JvdXBfYnkocG9zX2Nocl9zdGFydF9lbmQpICU+JSBkcGx5cjo6bXV0YXRlKGNvdW50c19zZXFzPW4oKSkgJT4lIGRwbHlyOjpmaWx0ZXIoY291bnRzX3NlcXMgPiAxKQpsaWJyYXJ5KGdncGxvdDIpCgpwcCA8LSBnZ3Bsb3QoY29tYmluZWRfbGlzdF9vZl9yZWdpb25zX0lEICU+JSBkcGx5cjo6Z3JvdXBfYnkocG9zX2Nocl9zdGFydF9lbmQpICU+JSBkcGx5cjo6YXJyYW5nZSguYnlfZ3JvdXAgPSBUUlVFKSAlPiUgZHBseXI6Om11dGF0ZShjb3VudHNfc2Vxcz1uKCkpICU+JSBkcGx5cjo6ZmlsdGVyKGNvdW50c19zZXFzID4gMSksCiAgICAgICBhZXMoeCA9IHBvc19jaHJfc3RhcnRfZW5kLAogICAgICAgICAgIHkgPSBhcy5mYWN0b3IoY2hyb20pLAogICAgICAgICAgIGNvbG9yPXBvc19jaHJfc3RhcnRfZW5kKSkgKyAKICAKICAjZ2VvbV9oaXN0b2dyYW0oc3RhdD0iY291bnQiKSArICNiaW53aWR0aCA9IDEpICsgCiAgI2dlb21fcG9pbnQoY29sb3I9InJlZCIpICsKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4yNSxoZWlnaHQgPSAwLjI1LHNlZWQgPSAxMjM0NTYpLHNpemU9MyxhbHBoYT0wLjUpICsKICAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpKSArCiAgI3NjYWxlX3lfZGlzY3JldGUoY2hyb20pICsKICAjY29vcmRfZmxpcCgpICsKICAjY3V0KCJjaHIiKSArCiAgI2dlb21fdGV4dChzdGF0ID0gImNvdW50IiwgYWVzKGxhYmVsID0gaWZlbHNlKGNvdW50ID49IDIsIGNvdW50LCAiIikpLCB2anVzdCA9IC0wLjI1KSArIAogIHhsYWIoIlBvc2l0aW9uIikgKyAKICB5bGFiKCJDb3VudCIpICsKICBmYWNldF93cmFwKH5JRCxuY29sPTEpICsKICBnZ3RpdGxlKCJQb2ludHMgb2YgTlVNVChzKSBQb3NpdGlvbnMiKQoKcHAKZGV2Lm9mZigpCgp3cml0ZS50YWJsZShjb21iaW5lZF9saXN0X29mX3JlZ2lvbnNfSUQgJT4lIGRwbHlyOjpncm91cF9ieShwb3NfY2hyX3N0YXJ0X2VuZCkgJT4lIGRwbHlyOjphcnJhbmdlKC5ieV9ncm91cCA9IFRSVUUpICU+JSBkcGx5cjo6bXV0YXRlKGNvdW50c19zZXFzPW4oKSksZmlsZSA9ICIvaG9tZS9ib3Rvcy9TVlJBVzEvYm90b3MvMjAyM18wMl8wOF9OVU1UUy9maW5hbF9udW10cy9UYWJsZS9Qb3N0aW9uc19pbl9DSFJfb2ZfbnVtdHMuY3N2IixzZXAgPSAiLCIpCgpgYGAKCiMjIENvdW5udCBvdmVybGFwcyBieSBzYW1wbGUgYW5kIGFsbCB0b2dldGhlciBhbmQgcGxvdCBDSVJDT1MKIyMjIFBlciBzYW1wbGUKYGBge3J9CmxpYnJhcnkocGx5cmFuZ2VzKQpuYW1lcyhsaXN0X29mX3JlZ2lvbnMpCmxpc3Rfb2ZfcmVnaW9uc19JRAojaHR0cHM6Ly9iaW9jb25kdWN0b3Iub3JnL3BhY2thZ2VzL2RldmVsL2Jpb2MvdmlnbmV0dGVzL0dlbm9taWNGZWF0dXJlcy9pbnN0L2RvYy9HZW5vbWljRmVhdHVyZXMuaHRtbApsaWJyYXJ5KFR4RGIuSHNhcGllbnMuVUNTQy5oZzE5Lmtub3duR2VuZSkKbGlicmFyeShHZW5vbWljUmFuZ2VzKQojRG93bmxvYWRlZCBmcm9tIE5DQkkKZ2ZmX2FlX3R4ZGIgPC0gbWFrZVR4RGJGcm9tR0ZGKGZpbGUgPSAiL2hvbWUvYm90b3MvU1ZSQVcxL2JvdG9zLzIwMjNfMDJfMDhfTlVNVFMvZmluYWxfbnVtdHMvRGF0YS9HQ0ZfMDAyMjA0NTE1LjJfQWFlZ0w1LjBfZ2Vub21pYy5nZmYiLGZvcm1hdCA9ICJnZmYzIixkYXRhU291cmNlID0gIk5DQkkiLG9yZ2FuaXNtID0gIkFlZGVzIGFlZ3lwdGkiLCkKCiNUaGlzIHdlcmUgc2VsZWN0ZWQgdXNpbmcgY3V0LGF3ayxncmVwIGJ5IGNvbW1hbmQgbGluZQpnZW5lcyhnZmZfYWVfdHhkYikKaGVhZChzZXFsZXZlbHMoZ2ZmX2FlX3R4ZGIpKQoKCiNzZWxlY3Qgb25seSBtdApjb2x1bW5zKGdmZl9hZV90eGRiKQpzZXFsZXZlbHMoZ2ZmX2FlX3R4ZGIpIDwtICJOQ18wMzUxNTkuMSIKI2Zyb20gdGhlIGZhc3RhICAvbG9jdXNfdGFnPSJDRkkwNl9tZ3AxMSIgICAgICAgICAgICAgICAgICAgICAgL2RiX3hyZWY9IkdlbmVJRDozMzMwNzU1OCIgICAgICBDRFMgICAgICAgICAgICAgMjkwMy4uMzU4NyAgICAgICAgICAgICAgICAgICAgICAvZ2VuZT0iQ09YMiIgCiNjb3gyLGF0cDgsYXRwNixjb3gzCiNnZW5lIG5hbWVzIGFyZSBub3QgY29ycmVjdGx5IGV4dHJyYWN0ZWQgZmZyb20gdGhlIGdmZiBmaWxlCmtleXNfMl9hYWVnIDwtIGMoIkNGSTA2X21ncDEyIiwiQ0ZJMDZfbWdwMTAiLCJDRkkwNl9tZ3AwOSIsIkNGSTA2X21ncDA4IikgCmtleXR5cGVzKGdmZl9hZV90eGRiKQpjb2x1bW5zKGdmZl9hZV90eGRiKQprZXlzKGdmZl9hZV90eGRiKQpBbm5vdGF0aW9uRGJpOjpzZWxlY3QoZ2ZmX2FlX3R4ZGIsa2V5cyA9IGtleXNfMl9hYWVnLGNvbHVtbnM9Y29sdW1ucyhnZmZfYWVfdHhkYiksIGtleXR5cGU9IkdFTkVJRCIpCiNBbm5vdGF0aW9uRGJpOjpzZWxlY3QoZ2ZmX2FlX3R4ZGIsa2V5cyA9IGtleXNfMl9hYWVnLGNvbHVtbnM9YygiVFhTVEFSVCIsIlRYRU5EIiwiVFhOQU1FIiwiQ0RTTkFNRSIsIkVYT05OQU1FIiksIGtleXR5cGU9IkdFTkVJRCIpCgoKI3JldHJpZXZlIGFsbCB0aGUgdHJhbnNjcmlwdHMgZnJvbSBtaXRvY2hvbmRyaWFsIGdlbm9tZSB1c2luZyB0aGlzIGZ1bmN0aW9uIGFzIGEgZ3Jhbmdlcwpncl9hYWVnX3RyYW5zY3JpcHRzICA8LSB0cmFuc2NyaXB0cyhnZmZfYWVfdHhkYikKZ3JfYWFlZ19nZW5lcyAgPC0gZ2VuZXMoZ2ZmX2FlX3R4ZGIpCgpncl9hYWVnX2dlbmVzWzE6M10KZ3JfYWFlZ190cmFuc2NyaXB0c1sxOjNdCgoKCgoKCiMjIyBDcmVhdGUgbGlzdCBvZiBncmFuZ2VzIHRvIGNvdW50IG92ZXJsYXBzIG9mIHRoZSBzYW1wbGVzIGZvciB0aGUgZGlmZmVyZW50IG51bXRzLgpsaXN0c19vZl9ncmFuZ2VzX251bXRzX2Nocl9kZXRhaWwgPC0gbGFwcGx5KGxpc3Rfb2ZfcmVnaW9uc19JRCxmdW5jdGlvbihkZikgeyAKICAjZ3JhbmdlX2xpc3QgPC0gbGlzdCgpCiAgI2dyYW5nZV9saXN0W1tsZW5ndGgoZ3JhbmdlX2xpc3QpICsgMV1dIAogIGRmICU+JSBkcGx5cjo6bXV0YXRlKHBvc19jaHJfc3RhcnRfZW5kID0gcGFzdGUwKCJjaHJNOiIsc3RhcnQsIi0iLGVuZCwiLW9yaWdpbi0iLGNocm9tKSkgJT4lICBkcGx5cjo6c2VsZWN0KHNlcW5hbWVzLHN0YXJ0LGVuZCxzdHJhbmQsY2hyb20sSUQscG9zX2Nocl9zdGFydF9lbmQpICU+JSBwbHlyYW5nZXM6OmFzX2dyYW5nZXMoKX0pCiAgI2dyYW5nZV9saXN0IDwtICAgIAogICNyZXR1cm4oZ3JhbmdlX2xpc3QpCgoKI0NlcmF0ZSBhIGxpc3Qgb2YgcmFuZ2VzIHRvIG92ZXJsYXAgdG8gdGhlIGdlbmVzIGluIHRoZSBDSFIgTVQgb2YgQWVkZXMgYWVneXB0aQpncmFuZ2VzX2xpc3RfYWVhZyA8LSBHUmFuZ2VzTGlzdChsaXN0c19vZl9ncmFuZ2VzX251bXRzX2Nocl9kZXRhaWwpCgoKCgoKIyNmaW5kIG92ZXJsYXBzIHVzaW5nIHBseXJhbmdlcyAodHV0b3JpYWwgaXMgcmVhbGx5IGhlbHBmdWwpCmdyX2FhZWdfZ2VuZXMgPC0gc29ydChncl9hYWVnX2dlbmVzKQpyZXN1bHRfbGlzdHNfYWFlZyA8LSBsaXN0KCkKcmVzdWx0X2xpc3RzX2FhZWdfZ2VuZXNfaGl0IDwtIGxpc3QoKQpmb3IgKGkgaW4gc2VxX2Fsb25nKDE6bGVuZ3RoKGdyYW5nZXNfbGlzdF9hZWFnKSkpewogIHByaW50KGkpCiAgcmVzdWx0X2xpc3RzX2FhZWdbW21jb2xzKGdyYW5nZXNfbGlzdF9hZWFnW1tpXV0pW1syXV1bMV1dXSA8LSBncmFuZ2VzX2xpc3RfYWVhZ1tbaV1dICU+JSAgam9pbl9vdmVybGFwX2lubmVyKGdyX2FhZWdfZ2VuZXMpCiAgcmVzdWx0X2xpc3RzX2FhZWdfZ2VuZXNfaGl0W1ttY29scyhncmFuZ2VzX2xpc3RfYWVhZ1tbaV1dKVtbMl1dWzFdXV0gPC0gcmVzdWx0X2xpc3RzX2FhZWdbW2ldXSAlPiUgYXMudGliYmxlKCkgJT4lCiAgICBkcGx5cjo6Z3JvdXBfYnkoZ2VuZV9pZCkgJT4lCiAgICBkcGx5cjo6c3VtbWFyaXNlKG51bXRzX2hpdHRpbmdfWF90aW1lX3RoZV9nZW5lPW4oKSkKICB9CgoKIyByZXN1bHRfbGlzdHNfYWFlZwojIHJlc3VsdF9saXN0c19hYWVnX2dlbmVzX2hpdAoKCmNvbnZlcnRlcl9nIDwtIHJlYWQudGFibGUoZmlsZSA9ICIvaG9tZS9ib3Rvcy9TVlJBVzEvYm90b3MvMjAyM18wMl8wOF9OVU1UUy9maW5hbF9udW10cy9EYXRhL2dlbmVzX2RieHJlZi5jc3YiLHNlcCA9ICIsIikKY29udmVydGVyX3QgPC0gcmVhZC50YWJsZShmaWxlID0gIi9ob21lL2JvdG9zL1NWUkFXMS9ib3Rvcy8yMDIzXzAyXzA4X05VTVRTL2ZpbmFsX251bXRzL0RhdGEvdHJuYXNfZGJ4cmVmLmNzdiIsc2VwID0gIiwiKQpjb252ZXJ0ZXJfdCA8LSBjb252ZXJ0ZXJfdFssYygyLDEpXQpuYW1lcyhjb252ZXJ0ZXJfdCkgPC0gYygiVjEiLCJWMiIpCmNvbnZlcnRlcl9ndCA8LSByYmluZChjb252ZXJ0ZXJfZyxjb252ZXJ0ZXJfdCkKbmFtZXMoY29udmVydGVyX2d0KSA8LSBjKCJzeW1ib2wiLCJkYnhyZWYiKQoKCiMjIyBDb252ZXJ0IHRoZSBkYnhyZWYgZ2VuZW4gbmFtZXMgdG8gc3ltYm9scwpyZXN1bHRfbGlzdHNfYWFlZ19nZW5lc19oaXRfd2l0aF9zeW1ib2wgPC0gbGFwcGx5KHJlc3VsdF9saXN0c19hYWVnX2dlbmVzX2hpdCxmdW5jdGlvbihubikgbm4gJT4lIGRwbHlyOjpsZWZ0X2pvaW4oY29udmVydGVyX2d0LGJ5ID0gYygiZ2VuZV9pZCIgPSAiZGJ4cmVmIikpKQoKCnJlc3VsdF9saXN0c19hYWVnX2dlbmVzX2hpdF93aXRoX3N5bWJvbF9jb3VudHMgPC0gbGFwcGx5KHJlc3VsdF9saXN0c19hYWVnX2dlbmVzX2hpdF93aXRoX3N5bWJvbCxmdW5jdGlvbihjYykgY2MgJT4lIGRwbHlyOjpncm91cF9ieShzeW1ib2wpICU+JSBkcGx5cjo6c3VtbWFyaXplKGNvdW50PWRwbHlyOjpuKCksY29sMl9zdW09c3VtKG51bXRzX2hpdHRpbmdfWF90aW1lX3RoZV9nZW5lKSkpCgpyZXN1bHRfbGlzdHNfYWFlZ19nZW5lc19oaXRfd2l0aF9zeW1ib2xfY291bnRzCgpgYGAKCgojIyMgbXRETkEgbnVtdHMgY2lyY29zIHBlciBzYW1wbGUKYGBge3IsZmlnLndpZHRoPTExLGZpZy5oZWlnaHQ9MTF9CgojbW09IldHU18wODhfRTIwX0YwNSIKIyByZXN1bHRfbGlzdHNfYWFlZ19nZW5lc19oaXRfd2l0aF9zeW1ib2xfY291bnRzW1siIl1dCgpsYXBwbHkobmFtZXMocmVzdWx0X2xpc3RzX2FhZWdfZ2VuZXNfaGl0X3dpdGhfc3ltYm9sX2NvdW50cyksZnVuY3Rpb24obW0pIHsKICBwcmludChwYXN0ZTAoInBsb3R0aW5nIGZvciBzYW1wbGUiLCBtbSkpCiAgCiAgI3BuZyhmaWxlbmFtZSA9IHBhc3RlMCgiL2hvbWUvYm90b3MvU1ZSQVcxL2JvdG9zLzIwMjNfMDJfMDhfTlVNVFMvVmlzdWFsaXphdGlvbl9zYW1wbGVzL1JfQ0lSQ09TX1JJTC8iLGRmW1siVjIiXV1bMV0sIi5wbmciKSx3aWR0aCA9IDY4MCxoZWlnaHQgPSA2ODApCiAgI3N2ZyhmaWxlbmFtZSA9IHBhc3RlMCgiL2hvbWUvYm90b3MvU1ZSQVcxL2JvdG9zLzIwMjNfMDJfMDhfTlVNVFMvZmluYWxfbnVtdHMvUGxvdHMvUklMX210RE5BX292ZXJsYXBfbnVtdHNfIixtbSwiX2NpcmNvcy5zdmciKSx3aWR0aCA9IDksaGVpZ2h0ID0gOSkKICAKICAKICBtdF9nZW5lc19hZV8yIDwtIG10X2dlbmVzX2FlCiAgbXRfZ2VuZXNfYWVfMiRzdGFydCA8LSBtdF9nZW5lc19hZV8yJHN0YXJ0LzEwMDAwMAogIG10X2dlbmVzX2FlXzIkZW5kIDwtIG10X2dlbmVzX2FlXzIkZW5kLzEwMDAwMAoKCiAgbnVtdHNfaGl0c19kZl9tZXJnZWRfY291bnRlZF9zdGFydF9lbmQgPC0gbXRfZ2VuZXNfYWVfMiAlPiUgZHBseXI6OnNlbGVjdChjaHIsc3RhcnQsZW5kLGdlbmUpICU+JQogICAgZHBseXI6OnJpZ2h0X2pvaW4ocmVzdWx0X2xpc3RzX2FhZWdfZ2VuZXNfaGl0X3dpdGhfc3ltYm9sX2NvdW50c1tbbW1dXSxieSA9IGMoImdlbmUiPSJzeW1ib2wiKSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKHZhbHVlPWNvbDJfc3VtKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoY2hyLHN0YXJ0LGVuZCx2YWx1ZSxnZW5lKSAlPiUKICAgIGRwbHlyOjphcnJhbmdlKHN0YXJ0LGVuZCkKICAKICAKICBudW10c19oaXRzX2RmX21lcmdlZF9jb3VudGVkX3N0YXJ0X2VuZCR2YWx1ZV9zY2FsZWQgPC0gbnVtdHNfaGl0c19kZl9tZXJnZWRfY291bnRlZF9zdGFydF9lbmQkdmFsdWUvMTAKCiAgCiAgCiAgbGlicmFyeShjaXJjbGl6ZSkKICByZWZfZmRfYWUgPC0gZGF0YS5mcmFtZSgiQ2hyb21vc29tZSI9YygiY2hyTSIpLCJDaHJvbVN0YXJ0Ij1jKDEpLCJDaHJvbWVuZCI9YygxNjc5MCkpCiAgI2NpcmNvcy5nZW5vbWljSW5pdGlhbGl6ZShyZWZfZmRfYWUpCiAgY2lyY29zLmdlbm9taWNJbml0aWFsaXplKHJlZl9mZF9hZSxwbG90VHlwZSA9IE5VTEwpCiAgY2lyY29zLmdlbm9taWNMYWJlbHMobXRfZ2VuZXNfYWVfMiAsCiAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzLmNvbHVtbiA9IDUsCiAgICAgICAgICAgICAgICAgICAgICAgY2V4PTAuNyxsaW5lX2x3ZD0wLjYsIGxpbmVfY29sPSJncmV5MjAiLAogICAgICAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25faGVpZ2h0ID0gMC4wMTksCiAgICAgICAgICAgICAgICAgICAgICAgY29sPWlmZWxzZShtdF9nZW5lc19hZV8yJGdlbmUgJWluJSBudW10c19oaXRzX2RmX21lcmdlZF9jb3VudGVkX3N0YXJ0X2VuZCRnZW5lW251bXRzX2hpdHNfZGZfbWVyZ2VkX2NvdW50ZWRfc3RhcnRfZW5kJHZhbHVlX3NjYWxlZCA+IG1lYW4obnVtdHNfaGl0c19kZl9tZXJnZWRfY291bnRlZF9zdGFydF9lbmQkdmFsdWVfc2NhbGVkKV0sInJlZCIsImJsYWNrIiksCiAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzX2hlaWdodCA9IDAuMixuaWNlRmFjaW5nID0gVFJVRSxzaWRlID0gIm91dHNpZGUiKQogIAogIAogICMgY2lyY29zLmdlbm9taWNMYWJlbHMobXRfZ2VuZXNfMiAsbGFiZWxzLmNvbHVtbiA9IDUsIGNleD0wLjUsbGluZV9sd2Q9MC42LCBsaW5lX2NvbD0iZ3JleTIwIiwgY29ubmVjdGlvbl9oZWlnaHQgPSAwLjA1LCBsYWJlbHNfaGVpZ2h0ID0gMC4yLG5pY2VGYWNpbmcgPSBUUlVFLHNpZGUgPSAib3V0c2lkZSIpCgogIGNpcmNvcy50cmFjayh5bGltPWMoMCwgMSksIHBhbmVsLmZ1bj1mdW5jdGlvbih4LCB5KSB7CiAgY2hyPUNFTExfTUVUQSRzZWN0b3IuaW5kZXgKICB4bGltPUNFTExfTUVUQSR4bGltCiAgeWxpbT1DRUxMX01FVEEkeWxpbSMKICBjaXJjb3MudGV4dChtZWFuKHhsaW0pLCBtZWFuKHlsaW0pLCBjaHIsIGNleD0wLjgpfSwgYmcuY29sID0gYygid2hpdGUiKSwgYmcuYm9yZGVyPUYsIHRyYWNrLmhlaWdodD0wLjIpICMgdGhlIHRyYWNrIGhlaWdodCBvZiB0aGUgdGV4dCBzcGVjaWZpZXMgaG93IHRoaWNrIGlzIHRoZSB0cmFjayB3ZXJlIHdlIHBsb3QgdGhlIGJhcnMKICAKICBjaXJjb3MudHJhY2sodHJhY2suaW5kZXggPSBnZXQuY3VycmVudC50cmFjay5pbmRleCgpLAogICAgICAgICAgICAgICB0cmFjay5oZWlnaHQ9MC44LAogICAgICAgICAgICAgICB5bGltPWMoMCwxKSwgI3RoaXMgdHJhY2sgeSBsaW0gc3BlY2lmaWVzIGhvdyBiaWcgYXJlIHRoZSBiYXJzIHVwIHRvIGluIHRoZSB0cmFjayB5IGxpbSAKICAgICAgICAgICAgICAgcGFuZWwuZnVuID0gZnVuY3Rpb24oeCwgeSkgewogICAgICAgICAgICAgICAgIGNpcmNvcy5nZW5vbWljQXhpcyhoID0gImJvdHRvbSIsIGRpcmVjdGlvbiA9ICJpbnNpZGUiLGxhYmVscy5jZXggPSAwLjYsdGlja0xhYmVsc1N0YXJ0RnJvbVplcm8gPSBGQUxTRSl9KQogICMgc2V0X3RyYWNrX2dhcChnYXAgPSAwLjA1KQogIAogIAogICMgZGRmZiA8LSBtdF9nZW5lc19hZV8yICU+JSBkcGx5cjo6c2VsZWN0KGNocixzdGFydCxlbmQsZ2VuZSkgJT4lIGRwbHlyOjpyaWdodF9qb2luKHJlc3VsdF9saXN0c19hYWVnX2dlbmVzX2hpdF93aXRoX3N5bWJvbF9jb3VudHMkV0dTXzIxMV9FMjBfRjAyLGJ5ID0gYygiZ2VuZSI9InN5bWJvbCIpKSAlPiVkcGx5cjo6bXV0YXRlKHZhbHVlPWNvbDJfc3VtKSAlPiUgZHBseXI6OnNlbGVjdChjaHIsc3RhcnQsZW5kLHZhbHVlLGdlbmUpICU+JSBkcGx5cjo6YXJyYW5nZShzdGFydCxlbmQpCiMgCiAgIyBkZGZmXzIgPC0gbXRfZ2VuZXNfYWVfMiAlPiUgZHBseXI6OnNlbGVjdChjaHIsc3RhcnQsZW5kLGdlbmUpICU+JSBkcGx5cjo6cmlnaHRfam9pbihyZXN1bHRfbGlzdHNfYWFlZ19nZW5lc19oaXRfd2l0aF9zeW1ib2xfY291bnRzJFdHU18wMzhfRTIwX0YwNyxieSA9IGMoImdlbmUiPSJzeW1ib2wiKSkgJT4lIGRwbHlyOjptdXRhdGUodmFsdWU9Y29sMl9zdW0pICU+JSBkcGx5cjo6c2VsZWN0KGNocixzdGFydCxlbmQsdmFsdWUsZ2VuZSkgJT4lIGRwbHlyOjphcnJhbmdlKHN0YXJ0LGVuZCkKCgogIGxpYnJhcnkoUkNvbG9yQnJld2VyKQogIGdyZWVuX3BhbCA8LSBjb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwoOSwgIkdyZWVucyIpKQoKIAogIG1hcF92YWx1ZV90b19jb2xvciA8LSBmdW5jdGlvbih2YWx1ZSkgewogICAgYnJlYWtzIDwtIHNlcSgwLDgsMC45KQogICAgY29sb3JzIDwtIGdyZWVuX3BhbCg5KQogICAgY29sb3JzW2ZpbmRJbnRlcnZhbCh2YWx1ZSwgYnJlYWtzKV0KICB9CiAgCiAgY2lyY29zLnJlY3QoeGxlZnQgPSBudW10c19oaXRzX2RmX21lcmdlZF9jb3VudGVkX3N0YXJ0X2VuZCRzdGFydCwKICAgICAgICAgICAgICB5Ym90dG9tID0gMC4wMSwKICAgICAgICAgICAgICB4cmlnaHQgPSBudW10c19oaXRzX2RmX21lcmdlZF9jb3VudGVkX3N0YXJ0X2VuZCRlbmQsCiAgICAgICAgICAgICAgeXRvcCA9IDAuMDIgKyBudW10c19oaXRzX2RmX21lcmdlZF9jb3VudGVkX3N0YXJ0X2VuZCR2YWx1ZV9zY2FsZWQsCiAgICAgICAgICAgICAgI2NvbCA9IHJnYigwLjQsIDAuNywgMC40LCBhbHBoYSA9IDAuNSksCiAgICAgICAgICAgICAgI2NvbCA9ICgiIzk1RDVCMiIpLAogICAgICAgICAgICAgIGNvbCA9IG1hcF92YWx1ZV90b19jb2xvcihudW10c19oaXRzX2RmX21lcmdlZF9jb3VudGVkX3N0YXJ0X2VuZCR2YWx1ZV9zY2FsZWQpLAogICAgICAgICAgICAgICNjb2wgPSBteV9jb2xvcnNfc2NhbGVkLAogICAgICAgICAgICAgIGJvcmRlciA9ICJibGFjayIpCiAgI2NpcmNvcy5saW5lcyhDRUxMX01FVEEkY2VsbC54bGltLCBjKG1heChudW10c19oaXRzX2RmX21lcmdlZF9jb3VudGVkX3N0YXJ0X2VuZCR2YWx1ZV9zY2FsZWQpKzAuMDIsIG1heChudW10c19oaXRzX2RmX21lcmdlZF9jb3VudGVkX3N0YXJ0X2VuZCR2YWx1ZV9zY2FsZWQpKzAuMiksbHdkID0gMiwgbHR5ID0gMiwgY29sID0gIiNBNzEyNDYiKQogICNjaXJjb3MubGluZXMoQ0VMTF9NRVRBJGNlbGwueGxpbSwgYyhtaW4obnVtdHNfaGl0c19kZl9tZXJnZWRfY291bnRlZF9zdGFydF9lbmQkdmFsdWUpKzUsIG1pbihudW10c19oaXRzX2RmX21lcmdlZF9jb3VudGVkX3N0YXJ0X2VuZCR2YWx1ZSkrNSksbHdkID0gMiwgbHR5ID0gMiwgY29sID0gImJsdWUiKQogIGNpcmNvcy5saW5lcyhDRUxMX01FVEEkY2VsbC54bGltLCBjKG1lYW4obnVtdHNfaGl0c19kZl9tZXJnZWRfY291bnRlZF9zdGFydF9lbmQkdmFsdWVfc2NhbGVkKSswLjAxLCBtZWFuKG51bXRzX2hpdHNfZGZfbWVyZ2VkX2NvdW50ZWRfc3RhcnRfZW5kJHZhbHVlX3NjYWxlZCkrMC4wMSksbHdkID0gMiwgbHR5ID0gMiwgY29sID0gIiMwMzA3MUUiKQogIAogIAogIAogICNkZXYub2ZmKCkKICAjcmVzdWx0X2xpc3RzX2FhZWdfZ2VuZXNfaGl0X3dpdGhfc3ltYm9sX2NvdW50c1tbbW1dXQp9KQoKCmxhcHBseShuYW1lcyhyZXN1bHRfbGlzdHNfYWFlZ19nZW5lc19oaXRfd2l0aF9zeW1ib2xfY291bnRzKSxmdW5jdGlvbihtbSkgewogIHByaW50KHBhc3RlMCgic2F2ZWQgc2FtcGxlIiwgbW0pKQogIHdyaXRlLnRhYmxlKHggPSByZXN1bHRfbGlzdHNfYWFlZ19nZW5lc19oaXRfd2l0aF9zeW1ib2xfY291bnRzW1ttbV1dLAogICAgICAgICAgICAgIGZpbGUgPSBwYXN0ZTAoIi9ob21lL2JvdG9zL1NWUkFXMS9ib3Rvcy8yMDIzXzAyXzA4X05VTVRTL2ZpbmFsX251bXRzL1RhYmxlL1JJTF9tdEROQV9vdmVybGFwX251bXRzXyIsbW0sIl9jaXJjb3NfdGFibGUuY3N2Iiksc2VwID0gIiwiKX0pCiAgICAgICAKYGBgCgoKCiMjIyBDb3VudCBhbGwgc2FtcGxlcyB0b2dldGhlciBhbmQgY2lyY29zIGl0LgpgYGB7cixmaWcud2lkdGg9MTEsZmlnLmhlaWdodD0xMX0KI0FkZCBjaXJjb3MKCiN0aGlzIHNjcmlwdCBydW4gZm9yIGFsbCB0aGUgc2FtcGxlcyBzdW1tZWQgdXAgZm9yIGFsbCBnZW5lcy4gY291bGQgYmUgYWxzbyBkb25lIGluZGl2aWR1YWxseS4KCiNwbmcoZmlsZW5hbWUgPSBwYXN0ZTAoIi9ob21lL2JvdG9zL1NWUkFXMS9ib3Rvcy8yMDIzXzAyXzA4X05VTVRTL1Zpc3VhbGl6YXRpb25fc2FtcGxlcy9SX0NJUkNPU19SSUwvIixkZltbIlYyIl1dWzFdLCIucG5nIiksd2lkdGggPSA2ODAsaGVpZ2h0ID0gNjgwKQpzdmcoZmlsZW5hbWUgPSBwYXN0ZTAoIi9ob21lL2JvdG9zL1NWUkFXMS9ib3Rvcy8yMDIzXzAyXzA4X05VTVRTL2ZpbmFsX251bXRzL1Bsb3RzL1JJTF9tdEROQV9udW10c19hbGxfc2FtcGxlc19jaXJjb3Muc3ZnIiksd2lkdGggPSA5LGhlaWdodCA9IDkpCgoKbnVtdHNfaGl0c19kZl9tZXJnZWQgPC0gZG8uY2FsbChyYmluZCxyZXN1bHRfbGlzdHNfYWFlZ19nZW5lc19oaXRfd2l0aF9zeW1ib2xfY291bnRzKQpudW10c19oaXRzX2RmX21lcmdlZF9jb3VudGVkIDwtIG51bXRzX2hpdHNfZGZfbWVyZ2VkICU+JSBkcGx5cjo6Z3JvdXBfYnkoc3ltYm9sKSAlPiUgZHBseXI6OnN1bW1hcml6ZShjb3VudD1kcGx5cjo6bigpLHRvdGFsX2FsbF9zYW1wbGVzX3N1bT1zdW0oY29sMl9zdW0pKQoKbXRfZ2VuZXNfYWVfMiA8LSBtdF9nZW5lc19hZQogIG10X2dlbmVzX2FlXzIkc3RhcnQgPC0gbXRfZ2VuZXNfYWVfMiRzdGFydC8xMDAwMDAKICBtdF9nZW5lc19hZV8yJGVuZCA8LSBtdF9nZW5lc19hZV8yJGVuZC8xMDAwMDAKCgpudW10c19oaXRzX2RmX21lcmdlZF9jb3VudGVkX3N0YXJ0X2VuZCA8LSBtdF9nZW5lc19hZV8yICU+JSBkcGx5cjo6c2VsZWN0KGNocixzdGFydCxlbmQsZ2VuZSkgJT4lIGRwbHlyOjpyaWdodF9qb2luKG51bXRzX2hpdHNfZGZfbWVyZ2VkX2NvdW50ZWQsYnkgPSBjKCJnZW5lIj0ic3ltYm9sIikpICU+JSBkcGx5cjo6bXV0YXRlKHZhbHVlPXRvdGFsX2FsbF9zYW1wbGVzX3N1bSkgJT4lIGRwbHlyOjpzZWxlY3QoY2hyLHN0YXJ0LGVuZCx2YWx1ZSxnZW5lKSAlPiUgZHBseXI6OmFycmFuZ2Uoc3RhcnQsZW5kKQoKCgoKbGlicmFyeShjaXJjbGl6ZSkKcmVmX2ZkX2FlIDwtIGRhdGEuZnJhbWUoIkNocm9tb3NvbWUiPWMoImNock0iKSwiQ2hyb21TdGFydCI9YygxKSwiQ2hyb21lbmQiPWMoMTY3OTApKQoKI2NpcmNvcy5nZW5vbWljSW5pdGlhbGl6ZShyZWZfZmRfYWUpCmNpcmNvcy5nZW5vbWljSW5pdGlhbGl6ZShyZWZfZmRfYWUscGxvdFR5cGUgPSBOVUxMKQoKbXRfZ2VuZXNfYWVfMiA8LSBtdF9nZW5lc19hZQptdF9nZW5lc19hZV8yJHN0YXJ0IDwtIG10X2dlbmVzX2FlXzIkc3RhcnQvMTAwMDAwCm10X2dlbmVzX2FlXzIkZW5kIDwtIG10X2dlbmVzX2FlXzIkZW5kLzEwMDAwMApjaXJjb3MuZ2Vub21pY0xhYmVscyhtdF9nZW5lc19hZV8yICxsYWJlbHMuY29sdW1uID0gNSwgY2V4PTAuNyxsaW5lX2x3ZD0wLjYsIGxpbmVfY29sPSJncmV5MjAiLCBjb25uZWN0aW9uX2hlaWdodCA9IDAuMDE5LGNvbD1pZmVsc2UobnVtdHNfaGl0c19kZl9tZXJnZWRfY291bnRlZF9zdGFydF9lbmQkdmFsdWUgPiBtZWFuKG51bXRzX2hpdHNfZGZfbWVyZ2VkX2NvdW50ZWRfc3RhcnRfZW5kJHZhbHVlKSwicmVkIiwiYmxhY2siKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzX2hlaWdodCA9IDAuMixuaWNlRmFjaW5nID0gVFJVRSxzaWRlID0gIm91dHNpZGUiKQojIGNpcmNvcy5nZW5vbWljTGFiZWxzKG10X2dlbmVzXzIgLGxhYmVscy5jb2x1bW4gPSA1LCBjZXg9MC41LGxpbmVfbHdkPTAuNiwgbGluZV9jb2w9ImdyZXkyMCIsIGNvbm5lY3Rpb25faGVpZ2h0ID0gMC4wNSwgbGFiZWxzX2hlaWdodCA9IDAuMixuaWNlRmFjaW5nID0gVFJVRSxzaWRlID0gIm91dHNpZGUiKQoKCgpjaXJjb3MudHJhY2soeWxpbT1jKDAsIDEpLCBwYW5lbC5mdW49ZnVuY3Rpb24oeCwgeSkgewpjaHI9Q0VMTF9NRVRBJHNlY3Rvci5pbmRleAp4bGltPUNFTExfTUVUQSR4bGltCnlsaW09Q0VMTF9NRVRBJHlsaW0jCmNpcmNvcy50ZXh0KG1lYW4oeGxpbSksIG1lYW4oeWxpbSksIGNociwgY2V4PTAuOCl9LCBiZy5jb2wgPSBjKCJ3aGl0ZSIpLCBiZy5ib3JkZXI9RiwgdHJhY2suaGVpZ2h0PTAuMikgIyB0aGUgdHJhY2sgaGVpZ2h0IG9mIHRoZSB0ZXh0IHNwZWNpZmllcyBob3cgdGhpY2sgaXMgdGhlIHRyYWNrIHdlcmUgd2UgcGxvdCB0aGUgYmFycwoKCmNpcmNvcy50cmFjayh0cmFjay5pbmRleCA9IGdldC5jdXJyZW50LnRyYWNrLmluZGV4KCksCiAgICAgICAgICAgICB0cmFjay5oZWlnaHQ9MC44LAogICAgICAgICAgICAgeWxpbT1jKDAsMTIwKSwgI3RoaXMgdHJhY2sgeSBsaW0gc3BlY2lmaWVzIGhvdyBiaWcgYXJlIHRoZSBiYXJzIHVwIHRvIGluIHRoZSB0cmFjayB5IGxpbSAKICAgICAgICAgICAgIHBhbmVsLmZ1biA9IGZ1bmN0aW9uKHgsIHkpIHsKICAgICAgICAgICAgICAgY2lyY29zLmdlbm9taWNBeGlzKGggPSAiYm90dG9tIiwgZGlyZWN0aW9uID0gImluc2lkZSIsbGFiZWxzLmNleCA9IDAuNix0aWNrTGFiZWxzU3RhcnRGcm9tWmVybyA9IEZBTFNFKX0pCiMgc2V0X3RyYWNrX2dhcChnYXAgPSAwLjA1KQoKCgpsaWJyYXJ5KFJDb2xvckJyZXdlcikKZ3JlZW5fcGFsIDwtIGNvbG9yUmFtcFBhbGV0dGUoYnJld2VyLnBhbCg5LCAiR3JlZW5zIikpCgoKbWFwX3ZhbHVlX3RvX2NvbG9yIDwtIGZ1bmN0aW9uKHZhbHVlKSB7CiAgYnJlYWtzIDwtIGMoMCwgMTAsIDIwLCAzMCwgNDAsIDUwLCA3MCwgOTAsMTEwICkKICBjb2xvcnMgPC0gZ3JlZW5fcGFsKDkpCiAgY29sb3JzW2ZpbmRJbnRlcnZhbCh2YWx1ZSwgYnJlYWtzKV0gCn0KCgoKY2lyY29zLnJlY3QoeGxlZnQgPSBudW10c19oaXRzX2RmX21lcmdlZF9jb3VudGVkX3N0YXJ0X2VuZCRzdGFydCwKICAgICAgICAgICAgeWJvdHRvbSA9IDUsCiAgICAgICAgICAgIHhyaWdodCA9IG51bXRzX2hpdHNfZGZfbWVyZ2VkX2NvdW50ZWRfc3RhcnRfZW5kJGVuZCwKICAgICAgICAgICAgeXRvcCA9IDUgKyBudW10c19oaXRzX2RmX21lcmdlZF9jb3VudGVkX3N0YXJ0X2VuZCR2YWx1ZSwKICAgICAgICAgICAgI2NvbCA9IHJnYigwLjQsIDAuNywgMC40LCBhbHBoYSA9IDAuNSksCiAgICAgICAgICAgICNjb2wgPSAoIiM5NUQ1QjIiKSwKICAgICAgICAgICAgY29sID0gbWFwX3ZhbHVlX3RvX2NvbG9yKG51bXRzX2hpdHNfZGZfbWVyZ2VkX2NvdW50ZWRfc3RhcnRfZW5kJHZhbHVlKSwKICAgICAgICAgICAgI2NvbCA9IG15X2NvbG9yc19zY2FsZWQsCiAgICAgICAgICAgIGJvcmRlciA9ICJibGFjayIpCmNpcmNvcy5saW5lcyhDRUxMX01FVEEkY2VsbC54bGltLCBjKG1heChudW10c19oaXRzX2RmX21lcmdlZF9jb3VudGVkX3N0YXJ0X2VuZCR2YWx1ZSkrNSwgbWF4KG51bXRzX2hpdHNfZGZfbWVyZ2VkX2NvdW50ZWRfc3RhcnRfZW5kJHZhbHVlKSs1KSxsd2QgPSAyLCBsdHkgPSAyLCBjb2wgPSAiI0E3MTI0NiIpCiNjaXJjb3MubGluZXMoQ0VMTF9NRVRBJGNlbGwueGxpbSwgYyhtaW4obnVtdHNfaGl0c19kZl9tZXJnZWRfY291bnRlZF9zdGFydF9lbmQkdmFsdWUpKzUsIG1pbihudW10c19oaXRzX2RmX21lcmdlZF9jb3VudGVkX3N0YXJ0X2VuZCR2YWx1ZSkrNSksbHdkID0gMiwgbHR5ID0gMiwgY29sID0gImJsdWUiKQpjaXJjb3MubGluZXMoQ0VMTF9NRVRBJGNlbGwueGxpbSwgYyhtZWFuKG51bXRzX2hpdHNfZGZfbWVyZ2VkX2NvdW50ZWRfc3RhcnRfZW5kJHZhbHVlKSs1LCBtZWFuKG51bXRzX2hpdHNfZGZfbWVyZ2VkX2NvdW50ZWRfc3RhcnRfZW5kJHZhbHVlKSs1KSxsd2QgPSAyLCBsdHkgPSAyLCBjb2wgPSAiIzAzMDcxRSIpCiAgIApkZXYub2ZmKCkKCgp3cml0ZS50YWJsZSh4ID0gbnVtdHNfaGl0c19kZl9tZXJnZWRfY291bnRlZF9zdGFydF9lbmQsZmlsZSA9IHBhc3RlMCgiL2hvbWUvYm90b3MvU1ZSQVcxL2JvdG9zLzIwMjNfMDJfMDhfTlVNVFMvZmluYWxfbnVtdHMvVGFibGUvUklMX210RE5BX251bXRzX2FsbF9zYW1wbGVzX2NpcmNvcy5jc3YiKSxzZXAgPSAiLCIpCgoKCmBgYApgYGB7cixmaWcud2lkdGg9MyxmaWcuaGVpZ2h0PTF9CmxpYnJhcnkoZ2dwbG90MikKCiMgQ3JlYXRlIHNhbXBsZSBkYXRhIHdpdGggb25lIGNvbHVtbiAidmFsdWUiIHJhbmdpbmcgZnJvbSAwIHRvIDEwMApkYXRhIDwtIGRhdGEuZnJhbWUodmFsdWUgPSAwOjEwNSkKCiMgQ3JlYXRlIGEgYmFyIHBsb3Qgd2l0aCBncmFkaWVudCBmaWxsCnN2ZyhmaWxlbmFtZSA9IHBhc3RlMCgiL2hvbWUvYm90b3MvU1ZSQVcxL2JvdG9zLzIwMjNfMDJfMDhfTlVNVFMvZmluYWxfbnVtdHMvUGxvdHMvUklMX210RE5BX251bXRzX2FsbF9zYW1wbGVzX2NpcmNvc19MRUdFTkQuc3ZnIiksd2lkdGggPSAzLGhlaWdodCA9IDQgKQpnZ3Bsb3QoZGF0YSwgYWVzKHggPSAxLCB5ID0gdmFsdWUsIGZpbGwgPSB2YWx1ZSkpICsgCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMSkgKwogIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGNvbG91cnMgPSBicmV3ZXIucGFsKDksICJHcmVlbnMiKSxndWlkZSA9ICJsZWdlbmQiKSArCiAgY29vcmRfZmxpcCgpICsKICB0aGVtZV92b2lkKCkKZGV2Lm9mZigpCgpgYGAKCmBgYHtyfQpzYXZlLmltYWdlKGZpbGUgPSAiL2hvbWUvYm90b3MvU1ZSQVcxL2JvdG9zLzIwMjNfMDJfMDhfTlVNVFMvZmluYWxfbnVtdHMvUi9udW10c19SX3Byb2Nlc3MuUkRhdGEiLGNvbXByZXNzID0gImd6aXAiKQpgYGAKCgoK